1646d67b5SJonathan Cameron // SPDX-License-Identifier: GPL-2.0+
2646d67b5SJonathan Cameron /*
3646d67b5SJonathan Cameron * AD7150 capacitive sensor driver supporting AD7150/1/6
4646d67b5SJonathan Cameron *
5646d67b5SJonathan Cameron * Copyright 2010-2011 Analog Devices Inc.
6646d67b5SJonathan Cameron * Copyright 2021 Jonathan Cameron <Jonathan.Cameron@huawei.com>
7646d67b5SJonathan Cameron */
8646d67b5SJonathan Cameron
9646d67b5SJonathan Cameron #include <linux/bitfield.h>
10646d67b5SJonathan Cameron #include <linux/device.h>
11646d67b5SJonathan Cameron #include <linux/interrupt.h>
12646d67b5SJonathan Cameron #include <linux/irq.h>
13646d67b5SJonathan Cameron #include <linux/i2c.h>
14646d67b5SJonathan Cameron #include <linux/kernel.h>
15646d67b5SJonathan Cameron #include <linux/module.h>
16646d67b5SJonathan Cameron #include <linux/mod_devicetable.h>
17646d67b5SJonathan Cameron #include <linux/regulator/consumer.h>
18646d67b5SJonathan Cameron #include <linux/slab.h>
19646d67b5SJonathan Cameron
20646d67b5SJonathan Cameron #include <linux/iio/iio.h>
21646d67b5SJonathan Cameron #include <linux/iio/sysfs.h>
22646d67b5SJonathan Cameron #include <linux/iio/events.h>
23646d67b5SJonathan Cameron
24646d67b5SJonathan Cameron #define AD7150_STATUS_REG 0
25646d67b5SJonathan Cameron #define AD7150_STATUS_OUT1 BIT(3)
26646d67b5SJonathan Cameron #define AD7150_STATUS_OUT2 BIT(5)
27646d67b5SJonathan Cameron #define AD7150_CH1_DATA_HIGH_REG 1
28646d67b5SJonathan Cameron #define AD7150_CH2_DATA_HIGH_REG 3
29646d67b5SJonathan Cameron #define AD7150_CH1_AVG_HIGH_REG 5
30646d67b5SJonathan Cameron #define AD7150_CH2_AVG_HIGH_REG 7
31646d67b5SJonathan Cameron #define AD7150_CH1_SENSITIVITY_REG 9
32646d67b5SJonathan Cameron #define AD7150_CH1_THR_HOLD_H_REG 9
33646d67b5SJonathan Cameron #define AD7150_CH1_TIMEOUT_REG 10
34646d67b5SJonathan Cameron #define AD7150_CH_TIMEOUT_RECEDING GENMASK(3, 0)
35646d67b5SJonathan Cameron #define AD7150_CH_TIMEOUT_APPROACHING GENMASK(7, 4)
36646d67b5SJonathan Cameron #define AD7150_CH1_SETUP_REG 11
37646d67b5SJonathan Cameron #define AD7150_CH2_SENSITIVITY_REG 12
38646d67b5SJonathan Cameron #define AD7150_CH2_THR_HOLD_H_REG 12
39646d67b5SJonathan Cameron #define AD7150_CH2_TIMEOUT_REG 13
40646d67b5SJonathan Cameron #define AD7150_CH2_SETUP_REG 14
41646d67b5SJonathan Cameron #define AD7150_CFG_REG 15
42646d67b5SJonathan Cameron #define AD7150_CFG_FIX BIT(7)
43646d67b5SJonathan Cameron #define AD7150_CFG_THRESHTYPE_MSK GENMASK(6, 5)
44646d67b5SJonathan Cameron #define AD7150_CFG_TT_NEG 0x0
45646d67b5SJonathan Cameron #define AD7150_CFG_TT_POS 0x1
46646d67b5SJonathan Cameron #define AD7150_CFG_TT_IN_WINDOW 0x2
47646d67b5SJonathan Cameron #define AD7150_CFG_TT_OUT_WINDOW 0x3
48646d67b5SJonathan Cameron #define AD7150_PD_TIMER_REG 16
49646d67b5SJonathan Cameron #define AD7150_CH1_CAPDAC_REG 17
50646d67b5SJonathan Cameron #define AD7150_CH2_CAPDAC_REG 18
51646d67b5SJonathan Cameron #define AD7150_SN3_REG 19
52646d67b5SJonathan Cameron #define AD7150_SN2_REG 20
53646d67b5SJonathan Cameron #define AD7150_SN1_REG 21
54646d67b5SJonathan Cameron #define AD7150_SN0_REG 22
55646d67b5SJonathan Cameron #define AD7150_ID_REG 23
56646d67b5SJonathan Cameron
57646d67b5SJonathan Cameron enum {
58646d67b5SJonathan Cameron AD7150,
59646d67b5SJonathan Cameron AD7151,
60646d67b5SJonathan Cameron };
61646d67b5SJonathan Cameron
62646d67b5SJonathan Cameron /**
63646d67b5SJonathan Cameron * struct ad7150_chip_info - instance specific chip data
64646d67b5SJonathan Cameron * @client: i2c client for this device
65646d67b5SJonathan Cameron * @threshold: thresholds for simple capacitance value events
66646d67b5SJonathan Cameron * @thresh_sensitivity: threshold for simple capacitance offset
67646d67b5SJonathan Cameron * from 'average' value.
68646d67b5SJonathan Cameron * @thresh_timeout: a timeout, in samples from the moment an
69646d67b5SJonathan Cameron * adaptive threshold event occurs to when the average
70646d67b5SJonathan Cameron * value jumps to current value. Note made up of two fields,
71646d67b5SJonathan Cameron * 3:0 are for timeout receding - applies if below lower threshold
72646d67b5SJonathan Cameron * 7:4 are for timeout approaching - applies if above upper threshold
73646d67b5SJonathan Cameron * @state_lock: ensure consistent state of this structure wrt the
74646d67b5SJonathan Cameron * hardware.
75646d67b5SJonathan Cameron * @interrupts: one or two interrupt numbers depending on device type.
76646d67b5SJonathan Cameron * @int_enabled: is a given interrupt currently enabled.
77646d67b5SJonathan Cameron * @type: threshold type
78646d67b5SJonathan Cameron * @dir: threshold direction
79646d67b5SJonathan Cameron */
80646d67b5SJonathan Cameron struct ad7150_chip_info {
81646d67b5SJonathan Cameron struct i2c_client *client;
82646d67b5SJonathan Cameron u16 threshold[2][2];
83646d67b5SJonathan Cameron u8 thresh_sensitivity[2][2];
84646d67b5SJonathan Cameron u8 thresh_timeout[2][2];
85646d67b5SJonathan Cameron struct mutex state_lock;
86646d67b5SJonathan Cameron int interrupts[2];
87646d67b5SJonathan Cameron bool int_enabled[2];
88646d67b5SJonathan Cameron enum iio_event_type type;
89646d67b5SJonathan Cameron enum iio_event_direction dir;
90646d67b5SJonathan Cameron };
91646d67b5SJonathan Cameron
92646d67b5SJonathan Cameron static const u8 ad7150_addresses[][6] = {
93646d67b5SJonathan Cameron { AD7150_CH1_DATA_HIGH_REG, AD7150_CH1_AVG_HIGH_REG,
94646d67b5SJonathan Cameron AD7150_CH1_SETUP_REG, AD7150_CH1_THR_HOLD_H_REG,
95646d67b5SJonathan Cameron AD7150_CH1_SENSITIVITY_REG, AD7150_CH1_TIMEOUT_REG },
96646d67b5SJonathan Cameron { AD7150_CH2_DATA_HIGH_REG, AD7150_CH2_AVG_HIGH_REG,
97646d67b5SJonathan Cameron AD7150_CH2_SETUP_REG, AD7150_CH2_THR_HOLD_H_REG,
98646d67b5SJonathan Cameron AD7150_CH2_SENSITIVITY_REG, AD7150_CH2_TIMEOUT_REG },
99646d67b5SJonathan Cameron };
100646d67b5SJonathan Cameron
ad7150_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)101646d67b5SJonathan Cameron static int ad7150_read_raw(struct iio_dev *indio_dev,
102646d67b5SJonathan Cameron struct iio_chan_spec const *chan,
103646d67b5SJonathan Cameron int *val,
104646d67b5SJonathan Cameron int *val2,
105646d67b5SJonathan Cameron long mask)
106646d67b5SJonathan Cameron {
107646d67b5SJonathan Cameron struct ad7150_chip_info *chip = iio_priv(indio_dev);
108646d67b5SJonathan Cameron int channel = chan->channel;
109646d67b5SJonathan Cameron int ret;
110646d67b5SJonathan Cameron
111646d67b5SJonathan Cameron switch (mask) {
112646d67b5SJonathan Cameron case IIO_CHAN_INFO_RAW:
113646d67b5SJonathan Cameron ret = i2c_smbus_read_word_swapped(chip->client,
114646d67b5SJonathan Cameron ad7150_addresses[channel][0]);
115646d67b5SJonathan Cameron if (ret < 0)
116646d67b5SJonathan Cameron return ret;
117646d67b5SJonathan Cameron *val = ret >> 4;
118646d67b5SJonathan Cameron
119646d67b5SJonathan Cameron return IIO_VAL_INT;
120646d67b5SJonathan Cameron case IIO_CHAN_INFO_AVERAGE_RAW:
121646d67b5SJonathan Cameron ret = i2c_smbus_read_word_swapped(chip->client,
122646d67b5SJonathan Cameron ad7150_addresses[channel][1]);
123646d67b5SJonathan Cameron if (ret < 0)
124646d67b5SJonathan Cameron return ret;
125646d67b5SJonathan Cameron *val = ret;
126646d67b5SJonathan Cameron
127646d67b5SJonathan Cameron return IIO_VAL_INT;
128646d67b5SJonathan Cameron case IIO_CHAN_INFO_SCALE:
129646d67b5SJonathan Cameron /*
130646d67b5SJonathan Cameron * Base units for capacitance are nano farads and the value
131646d67b5SJonathan Cameron * calculated from the datasheet formula is in picofarad
132646d67b5SJonathan Cameron * so multiply by 1000
133646d67b5SJonathan Cameron */
134646d67b5SJonathan Cameron *val = 1000;
135646d67b5SJonathan Cameron *val2 = 40944 >> 4; /* To match shift in _RAW */
136646d67b5SJonathan Cameron return IIO_VAL_FRACTIONAL;
137646d67b5SJonathan Cameron case IIO_CHAN_INFO_OFFSET:
138646d67b5SJonathan Cameron *val = -(12288 >> 4); /* To match shift in _RAW */
139646d67b5SJonathan Cameron return IIO_VAL_INT;
140646d67b5SJonathan Cameron case IIO_CHAN_INFO_SAMP_FREQ:
141646d67b5SJonathan Cameron /* Strangely same for both 1 and 2 chan parts */
142646d67b5SJonathan Cameron *val = 100;
143646d67b5SJonathan Cameron return IIO_VAL_INT;
144646d67b5SJonathan Cameron default:
145646d67b5SJonathan Cameron return -EINVAL;
146646d67b5SJonathan Cameron }
147646d67b5SJonathan Cameron }
148646d67b5SJonathan Cameron
ad7150_read_event_config(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir)149646d67b5SJonathan Cameron static int ad7150_read_event_config(struct iio_dev *indio_dev,
150646d67b5SJonathan Cameron const struct iio_chan_spec *chan,
151646d67b5SJonathan Cameron enum iio_event_type type,
152646d67b5SJonathan Cameron enum iio_event_direction dir)
153646d67b5SJonathan Cameron {
154646d67b5SJonathan Cameron struct ad7150_chip_info *chip = iio_priv(indio_dev);
155646d67b5SJonathan Cameron u8 threshtype;
156646d67b5SJonathan Cameron bool thrfixed;
157646d67b5SJonathan Cameron int ret;
158646d67b5SJonathan Cameron
159646d67b5SJonathan Cameron ret = i2c_smbus_read_byte_data(chip->client, AD7150_CFG_REG);
160646d67b5SJonathan Cameron if (ret < 0)
161646d67b5SJonathan Cameron return ret;
162646d67b5SJonathan Cameron
163646d67b5SJonathan Cameron threshtype = FIELD_GET(AD7150_CFG_THRESHTYPE_MSK, ret);
164646d67b5SJonathan Cameron
165646d67b5SJonathan Cameron /*check if threshold mode is fixed or adaptive*/
166646d67b5SJonathan Cameron thrfixed = FIELD_GET(AD7150_CFG_FIX, ret);
167646d67b5SJonathan Cameron
168646d67b5SJonathan Cameron switch (type) {
169646d67b5SJonathan Cameron case IIO_EV_TYPE_THRESH_ADAPTIVE:
170646d67b5SJonathan Cameron if (dir == IIO_EV_DIR_RISING)
171646d67b5SJonathan Cameron return !thrfixed && (threshtype == AD7150_CFG_TT_POS);
172646d67b5SJonathan Cameron return !thrfixed && (threshtype == AD7150_CFG_TT_NEG);
173646d67b5SJonathan Cameron case IIO_EV_TYPE_THRESH:
174646d67b5SJonathan Cameron if (dir == IIO_EV_DIR_RISING)
175646d67b5SJonathan Cameron return thrfixed && (threshtype == AD7150_CFG_TT_POS);
176646d67b5SJonathan Cameron return thrfixed && (threshtype == AD7150_CFG_TT_NEG);
177646d67b5SJonathan Cameron default:
178646d67b5SJonathan Cameron break;
179646d67b5SJonathan Cameron }
180646d67b5SJonathan Cameron return -EINVAL;
181646d67b5SJonathan Cameron }
182646d67b5SJonathan Cameron
183646d67b5SJonathan Cameron /* state_lock should be held to ensure consistent state */
ad7150_write_event_params(struct iio_dev * indio_dev,unsigned int chan,enum iio_event_type type,enum iio_event_direction dir)184646d67b5SJonathan Cameron static int ad7150_write_event_params(struct iio_dev *indio_dev,
185646d67b5SJonathan Cameron unsigned int chan,
186646d67b5SJonathan Cameron enum iio_event_type type,
187646d67b5SJonathan Cameron enum iio_event_direction dir)
188646d67b5SJonathan Cameron {
189646d67b5SJonathan Cameron struct ad7150_chip_info *chip = iio_priv(indio_dev);
190646d67b5SJonathan Cameron int rising = (dir == IIO_EV_DIR_RISING);
191646d67b5SJonathan Cameron
192646d67b5SJonathan Cameron /* Only update value live, if parameter is in use */
193646d67b5SJonathan Cameron if ((type != chip->type) || (dir != chip->dir))
194646d67b5SJonathan Cameron return 0;
195646d67b5SJonathan Cameron
196646d67b5SJonathan Cameron switch (type) {
197646d67b5SJonathan Cameron /* Note completely different from the adaptive versions */
198646d67b5SJonathan Cameron case IIO_EV_TYPE_THRESH: {
199646d67b5SJonathan Cameron u16 value = chip->threshold[rising][chan];
200646d67b5SJonathan Cameron return i2c_smbus_write_word_swapped(chip->client,
201646d67b5SJonathan Cameron ad7150_addresses[chan][3],
202646d67b5SJonathan Cameron value);
203646d67b5SJonathan Cameron }
204646d67b5SJonathan Cameron case IIO_EV_TYPE_THRESH_ADAPTIVE: {
205646d67b5SJonathan Cameron int ret;
206646d67b5SJonathan Cameron u8 sens, timeout;
207646d67b5SJonathan Cameron
208646d67b5SJonathan Cameron sens = chip->thresh_sensitivity[rising][chan];
209646d67b5SJonathan Cameron ret = i2c_smbus_write_byte_data(chip->client,
210646d67b5SJonathan Cameron ad7150_addresses[chan][4],
211646d67b5SJonathan Cameron sens);
212646d67b5SJonathan Cameron if (ret)
213646d67b5SJonathan Cameron return ret;
214646d67b5SJonathan Cameron
215646d67b5SJonathan Cameron /*
216646d67b5SJonathan Cameron * Single timeout register contains timeouts for both
217646d67b5SJonathan Cameron * directions.
218646d67b5SJonathan Cameron */
219646d67b5SJonathan Cameron timeout = FIELD_PREP(AD7150_CH_TIMEOUT_APPROACHING,
220646d67b5SJonathan Cameron chip->thresh_timeout[1][chan]);
221646d67b5SJonathan Cameron timeout |= FIELD_PREP(AD7150_CH_TIMEOUT_RECEDING,
222646d67b5SJonathan Cameron chip->thresh_timeout[0][chan]);
223646d67b5SJonathan Cameron return i2c_smbus_write_byte_data(chip->client,
224646d67b5SJonathan Cameron ad7150_addresses[chan][5],
225646d67b5SJonathan Cameron timeout);
226646d67b5SJonathan Cameron }
227646d67b5SJonathan Cameron default:
228646d67b5SJonathan Cameron return -EINVAL;
229646d67b5SJonathan Cameron }
230646d67b5SJonathan Cameron }
231646d67b5SJonathan Cameron
ad7150_write_event_config(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir,int state)232646d67b5SJonathan Cameron static int ad7150_write_event_config(struct iio_dev *indio_dev,
233646d67b5SJonathan Cameron const struct iio_chan_spec *chan,
234646d67b5SJonathan Cameron enum iio_event_type type,
235646d67b5SJonathan Cameron enum iio_event_direction dir, int state)
236646d67b5SJonathan Cameron {
237646d67b5SJonathan Cameron struct ad7150_chip_info *chip = iio_priv(indio_dev);
238032aec33SJonathan Cameron int ret = 0;
239646d67b5SJonathan Cameron
240646d67b5SJonathan Cameron /*
241646d67b5SJonathan Cameron * There is only a single shared control and no on chip
242646d67b5SJonathan Cameron * interrupt disables for the two interrupt lines.
243646d67b5SJonathan Cameron * So, enabling will switch the events configured to enable
244646d67b5SJonathan Cameron * whatever was most recently requested and if necessary enable_irq()
245646d67b5SJonathan Cameron * the interrupt and any disable will disable_irq() for that
246646d67b5SJonathan Cameron * channels interrupt.
247646d67b5SJonathan Cameron */
248646d67b5SJonathan Cameron if (!state) {
249646d67b5SJonathan Cameron if ((chip->int_enabled[chan->channel]) &&
250646d67b5SJonathan Cameron (type == chip->type) && (dir == chip->dir)) {
251646d67b5SJonathan Cameron disable_irq(chip->interrupts[chan->channel]);
252646d67b5SJonathan Cameron chip->int_enabled[chan->channel] = false;
253646d67b5SJonathan Cameron }
254646d67b5SJonathan Cameron return 0;
255646d67b5SJonathan Cameron }
256646d67b5SJonathan Cameron
257646d67b5SJonathan Cameron mutex_lock(&chip->state_lock);
258646d67b5SJonathan Cameron if ((type != chip->type) || (dir != chip->dir)) {
259646d67b5SJonathan Cameron int rising = (dir == IIO_EV_DIR_RISING);
260646d67b5SJonathan Cameron u8 thresh_type, cfg, fixed;
261646d67b5SJonathan Cameron
262646d67b5SJonathan Cameron /*
263646d67b5SJonathan Cameron * Need to temporarily disable both interrupts if
264646d67b5SJonathan Cameron * enabled - this is to avoid races around changing
265646d67b5SJonathan Cameron * config and thresholds.
266646d67b5SJonathan Cameron * Note enable/disable_irq() are reference counted so
267646d67b5SJonathan Cameron * no need to check if already enabled.
268646d67b5SJonathan Cameron */
269646d67b5SJonathan Cameron disable_irq(chip->interrupts[0]);
270646d67b5SJonathan Cameron disable_irq(chip->interrupts[1]);
271646d67b5SJonathan Cameron
272646d67b5SJonathan Cameron ret = i2c_smbus_read_byte_data(chip->client, AD7150_CFG_REG);
273646d67b5SJonathan Cameron if (ret < 0)
274646d67b5SJonathan Cameron goto error_ret;
275646d67b5SJonathan Cameron
276646d67b5SJonathan Cameron cfg = ret & ~(AD7150_CFG_THRESHTYPE_MSK | AD7150_CFG_FIX);
277646d67b5SJonathan Cameron
278646d67b5SJonathan Cameron if (type == IIO_EV_TYPE_THRESH_ADAPTIVE)
279646d67b5SJonathan Cameron fixed = 0;
280646d67b5SJonathan Cameron else
281646d67b5SJonathan Cameron fixed = 1;
282646d67b5SJonathan Cameron
283646d67b5SJonathan Cameron if (rising)
284646d67b5SJonathan Cameron thresh_type = AD7150_CFG_TT_POS;
285646d67b5SJonathan Cameron else
286646d67b5SJonathan Cameron thresh_type = AD7150_CFG_TT_NEG;
287646d67b5SJonathan Cameron
288646d67b5SJonathan Cameron cfg |= FIELD_PREP(AD7150_CFG_FIX, fixed) |
289646d67b5SJonathan Cameron FIELD_PREP(AD7150_CFG_THRESHTYPE_MSK, thresh_type);
290646d67b5SJonathan Cameron
291646d67b5SJonathan Cameron ret = i2c_smbus_write_byte_data(chip->client, AD7150_CFG_REG,
292646d67b5SJonathan Cameron cfg);
293646d67b5SJonathan Cameron if (ret < 0)
294646d67b5SJonathan Cameron goto error_ret;
295646d67b5SJonathan Cameron
296646d67b5SJonathan Cameron /*
297646d67b5SJonathan Cameron * There is a potential race condition here, but not easy
298646d67b5SJonathan Cameron * to close given we can't disable the interrupt at the
299646d67b5SJonathan Cameron * chip side of things. Rely on the status bit.
300646d67b5SJonathan Cameron */
301646d67b5SJonathan Cameron chip->type = type;
302646d67b5SJonathan Cameron chip->dir = dir;
303646d67b5SJonathan Cameron
304646d67b5SJonathan Cameron /* update control attributes */
305646d67b5SJonathan Cameron ret = ad7150_write_event_params(indio_dev, chan->channel, type,
306646d67b5SJonathan Cameron dir);
307646d67b5SJonathan Cameron if (ret)
308646d67b5SJonathan Cameron goto error_ret;
309646d67b5SJonathan Cameron /* reenable any irq's we disabled whilst changing mode */
310646d67b5SJonathan Cameron enable_irq(chip->interrupts[0]);
311646d67b5SJonathan Cameron enable_irq(chip->interrupts[1]);
312646d67b5SJonathan Cameron }
313646d67b5SJonathan Cameron if (!chip->int_enabled[chan->channel]) {
314646d67b5SJonathan Cameron enable_irq(chip->interrupts[chan->channel]);
315646d67b5SJonathan Cameron chip->int_enabled[chan->channel] = true;
316646d67b5SJonathan Cameron }
317646d67b5SJonathan Cameron
318646d67b5SJonathan Cameron error_ret:
319646d67b5SJonathan Cameron mutex_unlock(&chip->state_lock);
320646d67b5SJonathan Cameron
321646d67b5SJonathan Cameron return ret;
322646d67b5SJonathan Cameron }
323646d67b5SJonathan Cameron
ad7150_read_event_value(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir,enum iio_event_info info,int * val,int * val2)324646d67b5SJonathan Cameron static int ad7150_read_event_value(struct iio_dev *indio_dev,
325646d67b5SJonathan Cameron const struct iio_chan_spec *chan,
326646d67b5SJonathan Cameron enum iio_event_type type,
327646d67b5SJonathan Cameron enum iio_event_direction dir,
328646d67b5SJonathan Cameron enum iio_event_info info,
329646d67b5SJonathan Cameron int *val, int *val2)
330646d67b5SJonathan Cameron {
331646d67b5SJonathan Cameron struct ad7150_chip_info *chip = iio_priv(indio_dev);
332646d67b5SJonathan Cameron int rising = (dir == IIO_EV_DIR_RISING);
333646d67b5SJonathan Cameron
334646d67b5SJonathan Cameron /* Complex register sharing going on here */
335646d67b5SJonathan Cameron switch (info) {
336646d67b5SJonathan Cameron case IIO_EV_INFO_VALUE:
337646d67b5SJonathan Cameron switch (type) {
338646d67b5SJonathan Cameron case IIO_EV_TYPE_THRESH_ADAPTIVE:
339646d67b5SJonathan Cameron *val = chip->thresh_sensitivity[rising][chan->channel];
340646d67b5SJonathan Cameron return IIO_VAL_INT;
341646d67b5SJonathan Cameron case IIO_EV_TYPE_THRESH:
342646d67b5SJonathan Cameron *val = chip->threshold[rising][chan->channel];
343646d67b5SJonathan Cameron return IIO_VAL_INT;
344646d67b5SJonathan Cameron default:
345646d67b5SJonathan Cameron return -EINVAL;
346646d67b5SJonathan Cameron }
347646d67b5SJonathan Cameron case IIO_EV_INFO_TIMEOUT:
348646d67b5SJonathan Cameron *val = 0;
349646d67b5SJonathan Cameron *val2 = chip->thresh_timeout[rising][chan->channel] * 10000;
350646d67b5SJonathan Cameron return IIO_VAL_INT_PLUS_MICRO;
351646d67b5SJonathan Cameron default:
352646d67b5SJonathan Cameron return -EINVAL;
353646d67b5SJonathan Cameron }
354646d67b5SJonathan Cameron }
355646d67b5SJonathan Cameron
ad7150_write_event_value(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir,enum iio_event_info info,int val,int val2)356646d67b5SJonathan Cameron static int ad7150_write_event_value(struct iio_dev *indio_dev,
357646d67b5SJonathan Cameron const struct iio_chan_spec *chan,
358646d67b5SJonathan Cameron enum iio_event_type type,
359646d67b5SJonathan Cameron enum iio_event_direction dir,
360646d67b5SJonathan Cameron enum iio_event_info info,
361646d67b5SJonathan Cameron int val, int val2)
362646d67b5SJonathan Cameron {
363646d67b5SJonathan Cameron int ret;
364646d67b5SJonathan Cameron struct ad7150_chip_info *chip = iio_priv(indio_dev);
365646d67b5SJonathan Cameron int rising = (dir == IIO_EV_DIR_RISING);
366646d67b5SJonathan Cameron
367646d67b5SJonathan Cameron mutex_lock(&chip->state_lock);
368646d67b5SJonathan Cameron switch (info) {
369646d67b5SJonathan Cameron case IIO_EV_INFO_VALUE:
370646d67b5SJonathan Cameron switch (type) {
371646d67b5SJonathan Cameron case IIO_EV_TYPE_THRESH_ADAPTIVE:
372646d67b5SJonathan Cameron chip->thresh_sensitivity[rising][chan->channel] = val;
373646d67b5SJonathan Cameron break;
374646d67b5SJonathan Cameron case IIO_EV_TYPE_THRESH:
375646d67b5SJonathan Cameron chip->threshold[rising][chan->channel] = val;
376646d67b5SJonathan Cameron break;
377646d67b5SJonathan Cameron default:
378646d67b5SJonathan Cameron ret = -EINVAL;
379646d67b5SJonathan Cameron goto error_ret;
380646d67b5SJonathan Cameron }
381646d67b5SJonathan Cameron break;
382646d67b5SJonathan Cameron case IIO_EV_INFO_TIMEOUT: {
383646d67b5SJonathan Cameron /*
384646d67b5SJonathan Cameron * Raw timeout is in cycles of 10 msecs as long as both
385646d67b5SJonathan Cameron * channels are enabled.
386646d67b5SJonathan Cameron * In terms of INT_PLUS_MICRO, that is in units of 10,000
387646d67b5SJonathan Cameron */
388646d67b5SJonathan Cameron int timeout = val2 / 10000;
389646d67b5SJonathan Cameron
390646d67b5SJonathan Cameron if (val != 0 || timeout < 0 || timeout > 15 || val2 % 10000) {
391646d67b5SJonathan Cameron ret = -EINVAL;
392646d67b5SJonathan Cameron goto error_ret;
393646d67b5SJonathan Cameron }
394646d67b5SJonathan Cameron
395646d67b5SJonathan Cameron chip->thresh_timeout[rising][chan->channel] = timeout;
396646d67b5SJonathan Cameron break;
397646d67b5SJonathan Cameron }
398646d67b5SJonathan Cameron default:
399646d67b5SJonathan Cameron ret = -EINVAL;
400646d67b5SJonathan Cameron goto error_ret;
401646d67b5SJonathan Cameron }
402646d67b5SJonathan Cameron
403646d67b5SJonathan Cameron /* write back if active */
404646d67b5SJonathan Cameron ret = ad7150_write_event_params(indio_dev, chan->channel, type, dir);
405646d67b5SJonathan Cameron
406646d67b5SJonathan Cameron error_ret:
407646d67b5SJonathan Cameron mutex_unlock(&chip->state_lock);
408646d67b5SJonathan Cameron return ret;
409646d67b5SJonathan Cameron }
410646d67b5SJonathan Cameron
411646d67b5SJonathan Cameron static const struct iio_event_spec ad7150_events[] = {
412646d67b5SJonathan Cameron {
413646d67b5SJonathan Cameron .type = IIO_EV_TYPE_THRESH,
414646d67b5SJonathan Cameron .dir = IIO_EV_DIR_RISING,
415646d67b5SJonathan Cameron .mask_separate = BIT(IIO_EV_INFO_VALUE) |
416646d67b5SJonathan Cameron BIT(IIO_EV_INFO_ENABLE),
417646d67b5SJonathan Cameron }, {
418646d67b5SJonathan Cameron .type = IIO_EV_TYPE_THRESH,
419646d67b5SJonathan Cameron .dir = IIO_EV_DIR_FALLING,
420646d67b5SJonathan Cameron .mask_separate = BIT(IIO_EV_INFO_VALUE) |
421646d67b5SJonathan Cameron BIT(IIO_EV_INFO_ENABLE),
422646d67b5SJonathan Cameron }, {
423646d67b5SJonathan Cameron .type = IIO_EV_TYPE_THRESH_ADAPTIVE,
424646d67b5SJonathan Cameron .dir = IIO_EV_DIR_RISING,
425646d67b5SJonathan Cameron .mask_separate = BIT(IIO_EV_INFO_VALUE) |
426646d67b5SJonathan Cameron BIT(IIO_EV_INFO_ENABLE) |
427646d67b5SJonathan Cameron BIT(IIO_EV_INFO_TIMEOUT),
428646d67b5SJonathan Cameron }, {
429646d67b5SJonathan Cameron .type = IIO_EV_TYPE_THRESH_ADAPTIVE,
430646d67b5SJonathan Cameron .dir = IIO_EV_DIR_FALLING,
431646d67b5SJonathan Cameron .mask_separate = BIT(IIO_EV_INFO_VALUE) |
432646d67b5SJonathan Cameron BIT(IIO_EV_INFO_ENABLE) |
433646d67b5SJonathan Cameron BIT(IIO_EV_INFO_TIMEOUT),
434646d67b5SJonathan Cameron },
435646d67b5SJonathan Cameron };
436646d67b5SJonathan Cameron
437646d67b5SJonathan Cameron #define AD7150_CAPACITANCE_CHAN(_chan) { \
438646d67b5SJonathan Cameron .type = IIO_CAPACITANCE, \
439646d67b5SJonathan Cameron .indexed = 1, \
440646d67b5SJonathan Cameron .channel = _chan, \
441646d67b5SJonathan Cameron .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
442646d67b5SJonathan Cameron BIT(IIO_CHAN_INFO_AVERAGE_RAW), \
443646d67b5SJonathan Cameron .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
444646d67b5SJonathan Cameron BIT(IIO_CHAN_INFO_OFFSET), \
445646d67b5SJonathan Cameron .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\
446646d67b5SJonathan Cameron .event_spec = ad7150_events, \
447646d67b5SJonathan Cameron .num_event_specs = ARRAY_SIZE(ad7150_events), \
448646d67b5SJonathan Cameron }
449646d67b5SJonathan Cameron
450646d67b5SJonathan Cameron #define AD7150_CAPACITANCE_CHAN_NO_IRQ(_chan) { \
451646d67b5SJonathan Cameron .type = IIO_CAPACITANCE, \
452646d67b5SJonathan Cameron .indexed = 1, \
453646d67b5SJonathan Cameron .channel = _chan, \
454646d67b5SJonathan Cameron .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
455646d67b5SJonathan Cameron BIT(IIO_CHAN_INFO_AVERAGE_RAW), \
456646d67b5SJonathan Cameron .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
457646d67b5SJonathan Cameron BIT(IIO_CHAN_INFO_OFFSET), \
458646d67b5SJonathan Cameron .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\
459646d67b5SJonathan Cameron }
460646d67b5SJonathan Cameron
461646d67b5SJonathan Cameron static const struct iio_chan_spec ad7150_channels[] = {
462646d67b5SJonathan Cameron AD7150_CAPACITANCE_CHAN(0),
463646d67b5SJonathan Cameron AD7150_CAPACITANCE_CHAN(1),
464646d67b5SJonathan Cameron };
465646d67b5SJonathan Cameron
466646d67b5SJonathan Cameron static const struct iio_chan_spec ad7150_channels_no_irq[] = {
467646d67b5SJonathan Cameron AD7150_CAPACITANCE_CHAN_NO_IRQ(0),
468646d67b5SJonathan Cameron AD7150_CAPACITANCE_CHAN_NO_IRQ(1),
469646d67b5SJonathan Cameron };
470646d67b5SJonathan Cameron
471646d67b5SJonathan Cameron static const struct iio_chan_spec ad7151_channels[] = {
472646d67b5SJonathan Cameron AD7150_CAPACITANCE_CHAN(0),
473646d67b5SJonathan Cameron };
474646d67b5SJonathan Cameron
475646d67b5SJonathan Cameron static const struct iio_chan_spec ad7151_channels_no_irq[] = {
476646d67b5SJonathan Cameron AD7150_CAPACITANCE_CHAN_NO_IRQ(0),
477646d67b5SJonathan Cameron };
478646d67b5SJonathan Cameron
__ad7150_event_handler(void * private,u8 status_mask,int channel)479646d67b5SJonathan Cameron static irqreturn_t __ad7150_event_handler(void *private, u8 status_mask,
480646d67b5SJonathan Cameron int channel)
481646d67b5SJonathan Cameron {
482646d67b5SJonathan Cameron struct iio_dev *indio_dev = private;
483646d67b5SJonathan Cameron struct ad7150_chip_info *chip = iio_priv(indio_dev);
484646d67b5SJonathan Cameron s64 timestamp = iio_get_time_ns(indio_dev);
485646d67b5SJonathan Cameron int int_status;
486646d67b5SJonathan Cameron
487646d67b5SJonathan Cameron int_status = i2c_smbus_read_byte_data(chip->client, AD7150_STATUS_REG);
488646d67b5SJonathan Cameron if (int_status < 0)
489646d67b5SJonathan Cameron return IRQ_HANDLED;
490646d67b5SJonathan Cameron
491646d67b5SJonathan Cameron if (!(int_status & status_mask))
492646d67b5SJonathan Cameron return IRQ_HANDLED;
493646d67b5SJonathan Cameron
494646d67b5SJonathan Cameron iio_push_event(indio_dev,
495646d67b5SJonathan Cameron IIO_UNMOD_EVENT_CODE(IIO_CAPACITANCE, channel,
496646d67b5SJonathan Cameron chip->type, chip->dir),
497646d67b5SJonathan Cameron timestamp);
498646d67b5SJonathan Cameron
499646d67b5SJonathan Cameron return IRQ_HANDLED;
500646d67b5SJonathan Cameron }
501646d67b5SJonathan Cameron
ad7150_event_handler_ch1(int irq,void * private)502646d67b5SJonathan Cameron static irqreturn_t ad7150_event_handler_ch1(int irq, void *private)
503646d67b5SJonathan Cameron {
504646d67b5SJonathan Cameron return __ad7150_event_handler(private, AD7150_STATUS_OUT1, 0);
505646d67b5SJonathan Cameron }
506646d67b5SJonathan Cameron
ad7150_event_handler_ch2(int irq,void * private)507646d67b5SJonathan Cameron static irqreturn_t ad7150_event_handler_ch2(int irq, void *private)
508646d67b5SJonathan Cameron {
509646d67b5SJonathan Cameron return __ad7150_event_handler(private, AD7150_STATUS_OUT2, 1);
510646d67b5SJonathan Cameron }
511646d67b5SJonathan Cameron
512646d67b5SJonathan Cameron static IIO_CONST_ATTR(in_capacitance_thresh_adaptive_timeout_available,
513646d67b5SJonathan Cameron "[0 0.01 0.15]");
514646d67b5SJonathan Cameron
515646d67b5SJonathan Cameron static struct attribute *ad7150_event_attributes[] = {
516646d67b5SJonathan Cameron &iio_const_attr_in_capacitance_thresh_adaptive_timeout_available
517646d67b5SJonathan Cameron .dev_attr.attr,
518646d67b5SJonathan Cameron NULL,
519646d67b5SJonathan Cameron };
520646d67b5SJonathan Cameron
521646d67b5SJonathan Cameron static const struct attribute_group ad7150_event_attribute_group = {
522646d67b5SJonathan Cameron .attrs = ad7150_event_attributes,
523646d67b5SJonathan Cameron .name = "events",
524646d67b5SJonathan Cameron };
525646d67b5SJonathan Cameron
526646d67b5SJonathan Cameron static const struct iio_info ad7150_info = {
527646d67b5SJonathan Cameron .event_attrs = &ad7150_event_attribute_group,
528646d67b5SJonathan Cameron .read_raw = &ad7150_read_raw,
529646d67b5SJonathan Cameron .read_event_config = &ad7150_read_event_config,
530646d67b5SJonathan Cameron .write_event_config = &ad7150_write_event_config,
531646d67b5SJonathan Cameron .read_event_value = &ad7150_read_event_value,
532646d67b5SJonathan Cameron .write_event_value = &ad7150_write_event_value,
533646d67b5SJonathan Cameron };
534646d67b5SJonathan Cameron
535646d67b5SJonathan Cameron static const struct iio_info ad7150_info_no_irq = {
536646d67b5SJonathan Cameron .read_raw = &ad7150_read_raw,
537646d67b5SJonathan Cameron };
538646d67b5SJonathan Cameron
ad7150_probe(struct i2c_client * client)5397558eaa9SUwe Kleine-König static int ad7150_probe(struct i2c_client *client)
540646d67b5SJonathan Cameron {
5417558eaa9SUwe Kleine-König const struct i2c_device_id *id = i2c_client_get_device_id(client);
542646d67b5SJonathan Cameron struct ad7150_chip_info *chip;
543646d67b5SJonathan Cameron struct iio_dev *indio_dev;
544*b20f5801SMatti Vaittinen bool use_irq = true;
545646d67b5SJonathan Cameron int ret;
546646d67b5SJonathan Cameron
547646d67b5SJonathan Cameron indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
548646d67b5SJonathan Cameron if (!indio_dev)
549646d67b5SJonathan Cameron return -ENOMEM;
550646d67b5SJonathan Cameron
551646d67b5SJonathan Cameron chip = iio_priv(indio_dev);
552646d67b5SJonathan Cameron mutex_init(&chip->state_lock);
553646d67b5SJonathan Cameron chip->client = client;
554646d67b5SJonathan Cameron
555646d67b5SJonathan Cameron indio_dev->name = id->name;
556646d67b5SJonathan Cameron
557646d67b5SJonathan Cameron indio_dev->modes = INDIO_DIRECT_MODE;
558646d67b5SJonathan Cameron
55972ce527cSJonathan Cameron ret = devm_regulator_get_enable(&client->dev, "vdd");
560646d67b5SJonathan Cameron if (ret)
561646d67b5SJonathan Cameron return ret;
562646d67b5SJonathan Cameron
563646d67b5SJonathan Cameron chip->interrupts[0] = fwnode_irq_get(dev_fwnode(&client->dev), 0);
564646d67b5SJonathan Cameron if (chip->interrupts[0] < 0)
565*b20f5801SMatti Vaittinen use_irq = false;
566*b20f5801SMatti Vaittinen else if (id->driver_data == AD7150) {
567646d67b5SJonathan Cameron chip->interrupts[1] = fwnode_irq_get(dev_fwnode(&client->dev), 1);
568646d67b5SJonathan Cameron if (chip->interrupts[1] < 0)
569*b20f5801SMatti Vaittinen use_irq = false;
570646d67b5SJonathan Cameron }
571*b20f5801SMatti Vaittinen if (use_irq) {
572646d67b5SJonathan Cameron irq_set_status_flags(chip->interrupts[0], IRQ_NOAUTOEN);
573646d67b5SJonathan Cameron ret = devm_request_threaded_irq(&client->dev,
574646d67b5SJonathan Cameron chip->interrupts[0],
575646d67b5SJonathan Cameron NULL,
576646d67b5SJonathan Cameron &ad7150_event_handler_ch1,
577646d67b5SJonathan Cameron IRQF_TRIGGER_RISING |
578646d67b5SJonathan Cameron IRQF_ONESHOT,
579646d67b5SJonathan Cameron "ad7150_irq1",
580646d67b5SJonathan Cameron indio_dev);
581646d67b5SJonathan Cameron if (ret)
582646d67b5SJonathan Cameron return ret;
583646d67b5SJonathan Cameron
584646d67b5SJonathan Cameron indio_dev->info = &ad7150_info;
585646d67b5SJonathan Cameron switch (id->driver_data) {
586646d67b5SJonathan Cameron case AD7150:
587646d67b5SJonathan Cameron indio_dev->channels = ad7150_channels;
588646d67b5SJonathan Cameron indio_dev->num_channels = ARRAY_SIZE(ad7150_channels);
589646d67b5SJonathan Cameron irq_set_status_flags(chip->interrupts[1], IRQ_NOAUTOEN);
590646d67b5SJonathan Cameron ret = devm_request_threaded_irq(&client->dev,
591646d67b5SJonathan Cameron chip->interrupts[1],
592646d67b5SJonathan Cameron NULL,
593646d67b5SJonathan Cameron &ad7150_event_handler_ch2,
594646d67b5SJonathan Cameron IRQF_TRIGGER_RISING |
595646d67b5SJonathan Cameron IRQF_ONESHOT,
596646d67b5SJonathan Cameron "ad7150_irq2",
597646d67b5SJonathan Cameron indio_dev);
598646d67b5SJonathan Cameron if (ret)
599646d67b5SJonathan Cameron return ret;
600646d67b5SJonathan Cameron break;
601646d67b5SJonathan Cameron case AD7151:
602646d67b5SJonathan Cameron indio_dev->channels = ad7151_channels;
603646d67b5SJonathan Cameron indio_dev->num_channels = ARRAY_SIZE(ad7151_channels);
604646d67b5SJonathan Cameron break;
605646d67b5SJonathan Cameron default:
606646d67b5SJonathan Cameron return -EINVAL;
607646d67b5SJonathan Cameron }
608646d67b5SJonathan Cameron
609646d67b5SJonathan Cameron } else {
610646d67b5SJonathan Cameron indio_dev->info = &ad7150_info_no_irq;
611646d67b5SJonathan Cameron switch (id->driver_data) {
612646d67b5SJonathan Cameron case AD7150:
613646d67b5SJonathan Cameron indio_dev->channels = ad7150_channels_no_irq;
614646d67b5SJonathan Cameron indio_dev->num_channels =
615646d67b5SJonathan Cameron ARRAY_SIZE(ad7150_channels_no_irq);
616646d67b5SJonathan Cameron break;
617646d67b5SJonathan Cameron case AD7151:
618646d67b5SJonathan Cameron indio_dev->channels = ad7151_channels_no_irq;
619646d67b5SJonathan Cameron indio_dev->num_channels =
620646d67b5SJonathan Cameron ARRAY_SIZE(ad7151_channels_no_irq);
621646d67b5SJonathan Cameron break;
622646d67b5SJonathan Cameron default:
623646d67b5SJonathan Cameron return -EINVAL;
624646d67b5SJonathan Cameron }
625646d67b5SJonathan Cameron }
626646d67b5SJonathan Cameron
627646d67b5SJonathan Cameron return devm_iio_device_register(indio_dev->dev.parent, indio_dev);
628646d67b5SJonathan Cameron }
629646d67b5SJonathan Cameron
630646d67b5SJonathan Cameron static const struct i2c_device_id ad7150_id[] = {
631646d67b5SJonathan Cameron { "ad7150", AD7150 },
632646d67b5SJonathan Cameron { "ad7151", AD7151 },
633646d67b5SJonathan Cameron { "ad7156", AD7150 },
634646d67b5SJonathan Cameron {}
635646d67b5SJonathan Cameron };
636646d67b5SJonathan Cameron
637646d67b5SJonathan Cameron MODULE_DEVICE_TABLE(i2c, ad7150_id);
638646d67b5SJonathan Cameron
639646d67b5SJonathan Cameron static const struct of_device_id ad7150_of_match[] = {
640646d67b5SJonathan Cameron { "adi,ad7150" },
641646d67b5SJonathan Cameron { "adi,ad7151" },
642646d67b5SJonathan Cameron { "adi,ad7156" },
643646d67b5SJonathan Cameron {}
644646d67b5SJonathan Cameron };
645646d67b5SJonathan Cameron static struct i2c_driver ad7150_driver = {
646646d67b5SJonathan Cameron .driver = {
647646d67b5SJonathan Cameron .name = "ad7150",
648646d67b5SJonathan Cameron .of_match_table = ad7150_of_match,
649646d67b5SJonathan Cameron },
6507cf15f42SUwe Kleine-König .probe = ad7150_probe,
651646d67b5SJonathan Cameron .id_table = ad7150_id,
652646d67b5SJonathan Cameron };
653646d67b5SJonathan Cameron module_i2c_driver(ad7150_driver);
654646d67b5SJonathan Cameron
655646d67b5SJonathan Cameron MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
656646d67b5SJonathan Cameron MODULE_DESCRIPTION("Analog Devices AD7150/1/6 capacitive sensor driver");
657646d67b5SJonathan Cameron MODULE_LICENSE("GPL v2");
658