xref: /linux/drivers/iio/proximity/sx_common.c (revision 7008f35c4a7b25ea2e22bcaa14f21ae7aef49f2a)
1caa8ce7fSGwendal Grignou // SPDX-License-Identifier: GPL-2.0
2caa8ce7fSGwendal Grignou /*
3caa8ce7fSGwendal Grignou  * Copyright 2021 Google LLC.
4caa8ce7fSGwendal Grignou  *
5caa8ce7fSGwendal Grignou  * Common part of most Semtech SAR sensor.
6caa8ce7fSGwendal Grignou  */
7caa8ce7fSGwendal Grignou 
8caa8ce7fSGwendal Grignou #include <linux/acpi.h>
9caa8ce7fSGwendal Grignou #include <linux/bitops.h>
10caa8ce7fSGwendal Grignou #include <linux/byteorder/generic.h>
11caa8ce7fSGwendal Grignou #include <linux/delay.h>
12caa8ce7fSGwendal Grignou #include <linux/device.h>
13caa8ce7fSGwendal Grignou #include <linux/err.h>
14caa8ce7fSGwendal Grignou #include <linux/export.h>
15caa8ce7fSGwendal Grignou #include <linux/interrupt.h>
16caa8ce7fSGwendal Grignou #include <linux/irqreturn.h>
17caa8ce7fSGwendal Grignou #include <linux/i2c.h>
18caa8ce7fSGwendal Grignou #include <linux/kernel.h>
19caa8ce7fSGwendal Grignou #include <linux/module.h>
20caa8ce7fSGwendal Grignou #include <linux/regmap.h>
21caa8ce7fSGwendal Grignou #include <linux/regulator/consumer.h>
22caa8ce7fSGwendal Grignou #include <vdso/bits.h>
23caa8ce7fSGwendal Grignou 
24caa8ce7fSGwendal Grignou #include <linux/iio/buffer.h>
25caa8ce7fSGwendal Grignou #include <linux/iio/events.h>
26caa8ce7fSGwendal Grignou #include <linux/iio/iio.h>
27caa8ce7fSGwendal Grignou #include <linux/iio/trigger.h>
28caa8ce7fSGwendal Grignou #include <linux/iio/triggered_buffer.h>
29caa8ce7fSGwendal Grignou #include <linux/iio/trigger_consumer.h>
30caa8ce7fSGwendal Grignou 
31caa8ce7fSGwendal Grignou #include "sx_common.h"
32caa8ce7fSGwendal Grignou 
33caa8ce7fSGwendal Grignou /* All Semtech SAR sensors have IRQ bit in the same order. */
34caa8ce7fSGwendal Grignou #define   SX_COMMON_CONVDONE_IRQ			BIT(0)
35caa8ce7fSGwendal Grignou #define   SX_COMMON_FAR_IRQ				BIT(2)
36caa8ce7fSGwendal Grignou #define   SX_COMMON_CLOSE_IRQ				BIT(3)
37caa8ce7fSGwendal Grignou 
38caa8ce7fSGwendal Grignou const struct iio_event_spec sx_common_events[3] = {
39caa8ce7fSGwendal Grignou 	{
40caa8ce7fSGwendal Grignou 		.type = IIO_EV_TYPE_THRESH,
41caa8ce7fSGwendal Grignou 		.dir = IIO_EV_DIR_RISING,
42caa8ce7fSGwendal Grignou 		.mask_shared_by_all = BIT(IIO_EV_INFO_PERIOD),
43caa8ce7fSGwendal Grignou 	},
44caa8ce7fSGwendal Grignou 	{
45caa8ce7fSGwendal Grignou 		.type = IIO_EV_TYPE_THRESH,
46caa8ce7fSGwendal Grignou 		.dir = IIO_EV_DIR_FALLING,
47caa8ce7fSGwendal Grignou 		.mask_shared_by_all = BIT(IIO_EV_INFO_PERIOD),
48caa8ce7fSGwendal Grignou 	},
49caa8ce7fSGwendal Grignou 	{
50caa8ce7fSGwendal Grignou 		.type = IIO_EV_TYPE_THRESH,
51caa8ce7fSGwendal Grignou 		.dir = IIO_EV_DIR_EITHER,
52caa8ce7fSGwendal Grignou 		.mask_separate = BIT(IIO_EV_INFO_ENABLE) |
53caa8ce7fSGwendal Grignou 				 BIT(IIO_EV_INFO_HYSTERESIS) |
54caa8ce7fSGwendal Grignou 				 BIT(IIO_EV_INFO_VALUE),
55caa8ce7fSGwendal Grignou 	},
56caa8ce7fSGwendal Grignou };
57caa8ce7fSGwendal Grignou EXPORT_SYMBOL_NS_GPL(sx_common_events, SEMTECH_PROX);
58caa8ce7fSGwendal Grignou 
59caa8ce7fSGwendal Grignou static irqreturn_t sx_common_irq_handler(int irq, void *private)
60caa8ce7fSGwendal Grignou {
61caa8ce7fSGwendal Grignou 	struct iio_dev *indio_dev = private;
62caa8ce7fSGwendal Grignou 	struct sx_common_data *data = iio_priv(indio_dev);
63caa8ce7fSGwendal Grignou 
64caa8ce7fSGwendal Grignou 	if (data->trigger_enabled)
65caa8ce7fSGwendal Grignou 		iio_trigger_poll(data->trig);
66caa8ce7fSGwendal Grignou 
67caa8ce7fSGwendal Grignou 	/*
68caa8ce7fSGwendal Grignou 	 * Even if no event is enabled, we need to wake the thread to clear the
69caa8ce7fSGwendal Grignou 	 * interrupt state by reading SX_COMMON_REG_IRQ_SRC.
70caa8ce7fSGwendal Grignou 	 * It is not possible to do that here because regmap_read takes a mutex.
71caa8ce7fSGwendal Grignou 	 */
72caa8ce7fSGwendal Grignou 	return IRQ_WAKE_THREAD;
73caa8ce7fSGwendal Grignou }
74caa8ce7fSGwendal Grignou 
75caa8ce7fSGwendal Grignou static void sx_common_push_events(struct iio_dev *indio_dev)
76caa8ce7fSGwendal Grignou {
77caa8ce7fSGwendal Grignou 	int ret;
78caa8ce7fSGwendal Grignou 	unsigned int val, chan;
79caa8ce7fSGwendal Grignou 	struct sx_common_data *data = iio_priv(indio_dev);
80caa8ce7fSGwendal Grignou 	s64 timestamp = iio_get_time_ns(indio_dev);
81caa8ce7fSGwendal Grignou 	unsigned long prox_changed;
82caa8ce7fSGwendal Grignou 
83caa8ce7fSGwendal Grignou 	/* Read proximity state on all channels */
84caa8ce7fSGwendal Grignou 	ret = regmap_read(data->regmap, data->chip_info->reg_stat, &val);
85caa8ce7fSGwendal Grignou 	if (ret) {
86caa8ce7fSGwendal Grignou 		dev_err(&data->client->dev, "i2c transfer error in irq\n");
87caa8ce7fSGwendal Grignou 		return;
88caa8ce7fSGwendal Grignou 	}
89caa8ce7fSGwendal Grignou 
9019d32860SJongpil Jung 	val >>= data->chip_info->stat_offset;
91caa8ce7fSGwendal Grignou 
92caa8ce7fSGwendal Grignou 	/*
93caa8ce7fSGwendal Grignou 	 * Only iterate over channels with changes on proximity status that have
94caa8ce7fSGwendal Grignou 	 * events enabled.
95caa8ce7fSGwendal Grignou 	 */
96caa8ce7fSGwendal Grignou 	prox_changed = (data->chan_prox_stat ^ val) & data->chan_event;
97caa8ce7fSGwendal Grignou 
98caa8ce7fSGwendal Grignou 	for_each_set_bit(chan, &prox_changed, data->chip_info->num_channels) {
99caa8ce7fSGwendal Grignou 		int dir;
100caa8ce7fSGwendal Grignou 		u64 ev;
101caa8ce7fSGwendal Grignou 
102caa8ce7fSGwendal Grignou 		dir = (val & BIT(chan)) ? IIO_EV_DIR_FALLING : IIO_EV_DIR_RISING;
103caa8ce7fSGwendal Grignou 		ev = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, chan,
104caa8ce7fSGwendal Grignou 					  IIO_EV_TYPE_THRESH, dir);
105caa8ce7fSGwendal Grignou 
106caa8ce7fSGwendal Grignou 		iio_push_event(indio_dev, ev, timestamp);
107caa8ce7fSGwendal Grignou 	}
108caa8ce7fSGwendal Grignou 	data->chan_prox_stat = val;
109caa8ce7fSGwendal Grignou }
110caa8ce7fSGwendal Grignou 
111caa8ce7fSGwendal Grignou static int sx_common_enable_irq(struct sx_common_data *data, unsigned int irq)
112caa8ce7fSGwendal Grignou {
113caa8ce7fSGwendal Grignou 	if (!data->client->irq)
114caa8ce7fSGwendal Grignou 		return 0;
115caa8ce7fSGwendal Grignou 	return regmap_update_bits(data->regmap, data->chip_info->reg_irq_msk,
116caa8ce7fSGwendal Grignou 				  irq << data->chip_info->irq_msk_offset,
117caa8ce7fSGwendal Grignou 				  irq << data->chip_info->irq_msk_offset);
118caa8ce7fSGwendal Grignou }
119caa8ce7fSGwendal Grignou 
120caa8ce7fSGwendal Grignou static int sx_common_disable_irq(struct sx_common_data *data, unsigned int irq)
121caa8ce7fSGwendal Grignou {
122caa8ce7fSGwendal Grignou 	if (!data->client->irq)
123caa8ce7fSGwendal Grignou 		return 0;
124caa8ce7fSGwendal Grignou 	return regmap_update_bits(data->regmap, data->chip_info->reg_irq_msk,
125caa8ce7fSGwendal Grignou 				  irq << data->chip_info->irq_msk_offset, 0);
126caa8ce7fSGwendal Grignou }
127caa8ce7fSGwendal Grignou 
128caa8ce7fSGwendal Grignou static int sx_common_update_chan_en(struct sx_common_data *data,
129caa8ce7fSGwendal Grignou 				    unsigned long chan_read,
130caa8ce7fSGwendal Grignou 				    unsigned long chan_event)
131caa8ce7fSGwendal Grignou {
132caa8ce7fSGwendal Grignou 	int ret;
133caa8ce7fSGwendal Grignou 	unsigned long channels = chan_read | chan_event;
134caa8ce7fSGwendal Grignou 
135caa8ce7fSGwendal Grignou 	if ((data->chan_read | data->chan_event) != channels) {
136caa8ce7fSGwendal Grignou 		ret = regmap_update_bits(data->regmap,
137caa8ce7fSGwendal Grignou 					 data->chip_info->reg_enable_chan,
138caa8ce7fSGwendal Grignou 					 data->chip_info->mask_enable_chan,
139caa8ce7fSGwendal Grignou 					 channels);
140caa8ce7fSGwendal Grignou 		if (ret)
141caa8ce7fSGwendal Grignou 			return ret;
142caa8ce7fSGwendal Grignou 	}
143caa8ce7fSGwendal Grignou 	data->chan_read = chan_read;
144caa8ce7fSGwendal Grignou 	data->chan_event = chan_event;
145caa8ce7fSGwendal Grignou 	return 0;
146caa8ce7fSGwendal Grignou }
147caa8ce7fSGwendal Grignou 
148caa8ce7fSGwendal Grignou static int sx_common_get_read_channel(struct sx_common_data *data, int channel)
149caa8ce7fSGwendal Grignou {
150caa8ce7fSGwendal Grignou 	return sx_common_update_chan_en(data, data->chan_read | BIT(channel),
151caa8ce7fSGwendal Grignou 				     data->chan_event);
152caa8ce7fSGwendal Grignou }
153caa8ce7fSGwendal Grignou 
154caa8ce7fSGwendal Grignou static int sx_common_put_read_channel(struct sx_common_data *data, int channel)
155caa8ce7fSGwendal Grignou {
156caa8ce7fSGwendal Grignou 	return sx_common_update_chan_en(data, data->chan_read & ~BIT(channel),
157caa8ce7fSGwendal Grignou 				     data->chan_event);
158caa8ce7fSGwendal Grignou }
159caa8ce7fSGwendal Grignou 
160caa8ce7fSGwendal Grignou static int sx_common_get_event_channel(struct sx_common_data *data, int channel)
161caa8ce7fSGwendal Grignou {
162caa8ce7fSGwendal Grignou 	return sx_common_update_chan_en(data, data->chan_read,
163caa8ce7fSGwendal Grignou 				     data->chan_event | BIT(channel));
164caa8ce7fSGwendal Grignou }
165caa8ce7fSGwendal Grignou 
166caa8ce7fSGwendal Grignou static int sx_common_put_event_channel(struct sx_common_data *data, int channel)
167caa8ce7fSGwendal Grignou {
168caa8ce7fSGwendal Grignou 	return sx_common_update_chan_en(data, data->chan_read,
169caa8ce7fSGwendal Grignou 				     data->chan_event & ~BIT(channel));
170caa8ce7fSGwendal Grignou }
171caa8ce7fSGwendal Grignou 
172caa8ce7fSGwendal Grignou /**
173caa8ce7fSGwendal Grignou  * sx_common_read_proximity() - Read raw proximity value.
174caa8ce7fSGwendal Grignou  * @data:	Internal data
175caa8ce7fSGwendal Grignou  * @chan:	Channel to read
176caa8ce7fSGwendal Grignou  * @val:	pointer to return read value.
177caa8ce7fSGwendal Grignou  *
178caa8ce7fSGwendal Grignou  * Request a conversion, wait for the sensor to be ready and
179caa8ce7fSGwendal Grignou  * return the raw proximity value.
180caa8ce7fSGwendal Grignou  */
181caa8ce7fSGwendal Grignou int sx_common_read_proximity(struct sx_common_data *data,
182caa8ce7fSGwendal Grignou 			     const struct iio_chan_spec *chan, int *val)
183caa8ce7fSGwendal Grignou {
184caa8ce7fSGwendal Grignou 	int ret;
185caa8ce7fSGwendal Grignou 	__be16 rawval;
186caa8ce7fSGwendal Grignou 
187caa8ce7fSGwendal Grignou 	mutex_lock(&data->mutex);
188caa8ce7fSGwendal Grignou 
189caa8ce7fSGwendal Grignou 	ret = sx_common_get_read_channel(data, chan->channel);
190caa8ce7fSGwendal Grignou 	if (ret)
191caa8ce7fSGwendal Grignou 		goto out;
192caa8ce7fSGwendal Grignou 
193caa8ce7fSGwendal Grignou 	ret = sx_common_enable_irq(data, SX_COMMON_CONVDONE_IRQ);
194caa8ce7fSGwendal Grignou 	if (ret)
195caa8ce7fSGwendal Grignou 		goto out_put_channel;
196caa8ce7fSGwendal Grignou 
197caa8ce7fSGwendal Grignou 	mutex_unlock(&data->mutex);
198caa8ce7fSGwendal Grignou 
199caa8ce7fSGwendal Grignou 	if (data->client->irq) {
200caa8ce7fSGwendal Grignou 		ret = wait_for_completion_interruptible(&data->completion);
201caa8ce7fSGwendal Grignou 		reinit_completion(&data->completion);
202caa8ce7fSGwendal Grignou 	} else {
203caa8ce7fSGwendal Grignou 		ret = data->chip_info->ops.wait_for_sample(data);
204caa8ce7fSGwendal Grignou 	}
205caa8ce7fSGwendal Grignou 
206caa8ce7fSGwendal Grignou 	mutex_lock(&data->mutex);
207caa8ce7fSGwendal Grignou 
208caa8ce7fSGwendal Grignou 	if (ret)
209caa8ce7fSGwendal Grignou 		goto out_disable_irq;
210caa8ce7fSGwendal Grignou 
211caa8ce7fSGwendal Grignou 	ret = data->chip_info->ops.read_prox_data(data, chan, &rawval);
212caa8ce7fSGwendal Grignou 	if (ret)
213caa8ce7fSGwendal Grignou 		goto out_disable_irq;
214caa8ce7fSGwendal Grignou 
215caa8ce7fSGwendal Grignou 	*val = sign_extend32(be16_to_cpu(rawval), chan->scan_type.realbits - 1);
216caa8ce7fSGwendal Grignou 
217caa8ce7fSGwendal Grignou 	ret = sx_common_disable_irq(data, SX_COMMON_CONVDONE_IRQ);
218caa8ce7fSGwendal Grignou 	if (ret)
219caa8ce7fSGwendal Grignou 		goto out_put_channel;
220caa8ce7fSGwendal Grignou 
221caa8ce7fSGwendal Grignou 	ret = sx_common_put_read_channel(data, chan->channel);
222caa8ce7fSGwendal Grignou 	if (ret)
223caa8ce7fSGwendal Grignou 		goto out;
224caa8ce7fSGwendal Grignou 
225caa8ce7fSGwendal Grignou 	mutex_unlock(&data->mutex);
226caa8ce7fSGwendal Grignou 
227caa8ce7fSGwendal Grignou 	return IIO_VAL_INT;
228caa8ce7fSGwendal Grignou 
229caa8ce7fSGwendal Grignou out_disable_irq:
230caa8ce7fSGwendal Grignou 	sx_common_disable_irq(data, SX_COMMON_CONVDONE_IRQ);
231caa8ce7fSGwendal Grignou out_put_channel:
232caa8ce7fSGwendal Grignou 	sx_common_put_read_channel(data, chan->channel);
233caa8ce7fSGwendal Grignou out:
234caa8ce7fSGwendal Grignou 	mutex_unlock(&data->mutex);
235caa8ce7fSGwendal Grignou 
236caa8ce7fSGwendal Grignou 	return ret;
237caa8ce7fSGwendal Grignou }
238caa8ce7fSGwendal Grignou EXPORT_SYMBOL_NS_GPL(sx_common_read_proximity, SEMTECH_PROX);
239caa8ce7fSGwendal Grignou 
240caa8ce7fSGwendal Grignou /**
241caa8ce7fSGwendal Grignou  * sx_common_read_event_config() - Configure event setting.
242caa8ce7fSGwendal Grignou  * @indio_dev:	iio device object
243caa8ce7fSGwendal Grignou  * @chan:	Channel to read
244caa8ce7fSGwendal Grignou  * @type:	Type of event (unused)
245caa8ce7fSGwendal Grignou  * @dir:	Direction of event (unused)
246caa8ce7fSGwendal Grignou  *
247caa8ce7fSGwendal Grignou  * return if the given channel is used for event gathering.
248caa8ce7fSGwendal Grignou  */
249caa8ce7fSGwendal Grignou int sx_common_read_event_config(struct iio_dev *indio_dev,
250caa8ce7fSGwendal Grignou 				const struct iio_chan_spec *chan,
251caa8ce7fSGwendal Grignou 				enum iio_event_type type,
252caa8ce7fSGwendal Grignou 				enum iio_event_direction dir)
253caa8ce7fSGwendal Grignou {
254caa8ce7fSGwendal Grignou 	struct sx_common_data *data = iio_priv(indio_dev);
255caa8ce7fSGwendal Grignou 
256caa8ce7fSGwendal Grignou 	return !!(data->chan_event & BIT(chan->channel));
257caa8ce7fSGwendal Grignou }
258caa8ce7fSGwendal Grignou EXPORT_SYMBOL_NS_GPL(sx_common_read_event_config, SEMTECH_PROX);
259caa8ce7fSGwendal Grignou 
260caa8ce7fSGwendal Grignou /**
261caa8ce7fSGwendal Grignou  * sx_common_write_event_config() - Configure event setting.
262caa8ce7fSGwendal Grignou  * @indio_dev:	iio device object
263caa8ce7fSGwendal Grignou  * @chan:	Channel to enable
264caa8ce7fSGwendal Grignou  * @type:	Type of event (unused)
265caa8ce7fSGwendal Grignou  * @dir:	Direction of event (unused)
266caa8ce7fSGwendal Grignou  * @state:	State of the event.
267caa8ce7fSGwendal Grignou  *
268caa8ce7fSGwendal Grignou  * Enable/Disable event on a given channel.
269caa8ce7fSGwendal Grignou  */
270caa8ce7fSGwendal Grignou int sx_common_write_event_config(struct iio_dev *indio_dev,
271caa8ce7fSGwendal Grignou 				 const struct iio_chan_spec *chan,
272caa8ce7fSGwendal Grignou 				 enum iio_event_type type,
273caa8ce7fSGwendal Grignou 				 enum iio_event_direction dir, int state)
274caa8ce7fSGwendal Grignou {
275caa8ce7fSGwendal Grignou 	struct sx_common_data *data = iio_priv(indio_dev);
276caa8ce7fSGwendal Grignou 	unsigned int eventirq = SX_COMMON_FAR_IRQ | SX_COMMON_CLOSE_IRQ;
277caa8ce7fSGwendal Grignou 	int ret;
278caa8ce7fSGwendal Grignou 
279caa8ce7fSGwendal Grignou 	/* If the state hasn't changed, there's nothing to do. */
280caa8ce7fSGwendal Grignou 	if (!!(data->chan_event & BIT(chan->channel)) == state)
281caa8ce7fSGwendal Grignou 		return 0;
282caa8ce7fSGwendal Grignou 
283caa8ce7fSGwendal Grignou 	mutex_lock(&data->mutex);
284caa8ce7fSGwendal Grignou 	if (state) {
285caa8ce7fSGwendal Grignou 		ret = sx_common_get_event_channel(data, chan->channel);
286caa8ce7fSGwendal Grignou 		if (ret)
287caa8ce7fSGwendal Grignou 			goto out_unlock;
288caa8ce7fSGwendal Grignou 		if (!(data->chan_event & ~BIT(chan->channel))) {
289caa8ce7fSGwendal Grignou 			ret = sx_common_enable_irq(data, eventirq);
290caa8ce7fSGwendal Grignou 			if (ret)
291caa8ce7fSGwendal Grignou 				sx_common_put_event_channel(data, chan->channel);
292caa8ce7fSGwendal Grignou 		}
293caa8ce7fSGwendal Grignou 	} else {
294caa8ce7fSGwendal Grignou 		ret = sx_common_put_event_channel(data, chan->channel);
295caa8ce7fSGwendal Grignou 		if (ret)
296caa8ce7fSGwendal Grignou 			goto out_unlock;
297caa8ce7fSGwendal Grignou 		if (!data->chan_event) {
298caa8ce7fSGwendal Grignou 			ret = sx_common_disable_irq(data, eventirq);
299caa8ce7fSGwendal Grignou 			if (ret)
300caa8ce7fSGwendal Grignou 				sx_common_get_event_channel(data, chan->channel);
301caa8ce7fSGwendal Grignou 		}
302caa8ce7fSGwendal Grignou 	}
303caa8ce7fSGwendal Grignou 
304caa8ce7fSGwendal Grignou out_unlock:
305caa8ce7fSGwendal Grignou 	mutex_unlock(&data->mutex);
306caa8ce7fSGwendal Grignou 	return ret;
307caa8ce7fSGwendal Grignou }
308caa8ce7fSGwendal Grignou EXPORT_SYMBOL_NS_GPL(sx_common_write_event_config, SEMTECH_PROX);
309caa8ce7fSGwendal Grignou 
310caa8ce7fSGwendal Grignou static int sx_common_set_trigger_state(struct iio_trigger *trig, bool state)
311caa8ce7fSGwendal Grignou {
312caa8ce7fSGwendal Grignou 	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
313caa8ce7fSGwendal Grignou 	struct sx_common_data *data = iio_priv(indio_dev);
314caa8ce7fSGwendal Grignou 	int ret = 0;
315caa8ce7fSGwendal Grignou 
316caa8ce7fSGwendal Grignou 	mutex_lock(&data->mutex);
317caa8ce7fSGwendal Grignou 
318caa8ce7fSGwendal Grignou 	if (state)
319caa8ce7fSGwendal Grignou 		ret = sx_common_enable_irq(data, SX_COMMON_CONVDONE_IRQ);
320caa8ce7fSGwendal Grignou 	else if (!data->chan_read)
321caa8ce7fSGwendal Grignou 		ret = sx_common_disable_irq(data, SX_COMMON_CONVDONE_IRQ);
322caa8ce7fSGwendal Grignou 	if (ret)
323caa8ce7fSGwendal Grignou 		goto out;
324caa8ce7fSGwendal Grignou 
325caa8ce7fSGwendal Grignou 	data->trigger_enabled = state;
326caa8ce7fSGwendal Grignou 
327caa8ce7fSGwendal Grignou out:
328caa8ce7fSGwendal Grignou 	mutex_unlock(&data->mutex);
329caa8ce7fSGwendal Grignou 
330caa8ce7fSGwendal Grignou 	return ret;
331caa8ce7fSGwendal Grignou }
332caa8ce7fSGwendal Grignou 
333caa8ce7fSGwendal Grignou static const struct iio_trigger_ops sx_common_trigger_ops = {
334caa8ce7fSGwendal Grignou 	.set_trigger_state = sx_common_set_trigger_state,
335caa8ce7fSGwendal Grignou };
336caa8ce7fSGwendal Grignou 
337caa8ce7fSGwendal Grignou static irqreturn_t sx_common_irq_thread_handler(int irq, void *private)
338caa8ce7fSGwendal Grignou {
339caa8ce7fSGwendal Grignou 	struct iio_dev *indio_dev = private;
340caa8ce7fSGwendal Grignou 	struct sx_common_data *data = iio_priv(indio_dev);
341caa8ce7fSGwendal Grignou 	int ret;
342caa8ce7fSGwendal Grignou 	unsigned int val;
343caa8ce7fSGwendal Grignou 
344caa8ce7fSGwendal Grignou 	mutex_lock(&data->mutex);
345caa8ce7fSGwendal Grignou 
346caa8ce7fSGwendal Grignou 	ret = regmap_read(data->regmap, SX_COMMON_REG_IRQ_SRC, &val);
347caa8ce7fSGwendal Grignou 	if (ret) {
348caa8ce7fSGwendal Grignou 		dev_err(&data->client->dev, "i2c transfer error in irq\n");
349caa8ce7fSGwendal Grignou 		goto out;
350caa8ce7fSGwendal Grignou 	}
351caa8ce7fSGwendal Grignou 
352caa8ce7fSGwendal Grignou 	if (val & ((SX_COMMON_FAR_IRQ | SX_COMMON_CLOSE_IRQ) << data->chip_info->irq_msk_offset))
353caa8ce7fSGwendal Grignou 		sx_common_push_events(indio_dev);
354caa8ce7fSGwendal Grignou 
355caa8ce7fSGwendal Grignou 	if (val & (SX_COMMON_CONVDONE_IRQ << data->chip_info->irq_msk_offset))
356caa8ce7fSGwendal Grignou 		complete(&data->completion);
357caa8ce7fSGwendal Grignou 
358caa8ce7fSGwendal Grignou out:
359caa8ce7fSGwendal Grignou 	mutex_unlock(&data->mutex);
360caa8ce7fSGwendal Grignou 
361caa8ce7fSGwendal Grignou 	return IRQ_HANDLED;
362caa8ce7fSGwendal Grignou }
363caa8ce7fSGwendal Grignou 
364caa8ce7fSGwendal Grignou static irqreturn_t sx_common_trigger_handler(int irq, void *private)
365caa8ce7fSGwendal Grignou {
366caa8ce7fSGwendal Grignou 	struct iio_poll_func *pf = private;
367caa8ce7fSGwendal Grignou 	struct iio_dev *indio_dev = pf->indio_dev;
368caa8ce7fSGwendal Grignou 	struct sx_common_data *data = iio_priv(indio_dev);
369caa8ce7fSGwendal Grignou 	__be16 val;
370caa8ce7fSGwendal Grignou 	int bit, ret, i = 0;
371caa8ce7fSGwendal Grignou 
372caa8ce7fSGwendal Grignou 	mutex_lock(&data->mutex);
373caa8ce7fSGwendal Grignou 
374caa8ce7fSGwendal Grignou 	for_each_set_bit(bit, indio_dev->active_scan_mask,
375caa8ce7fSGwendal Grignou 			 indio_dev->masklength) {
376caa8ce7fSGwendal Grignou 		ret = data->chip_info->ops.read_prox_data(data,
377caa8ce7fSGwendal Grignou 						     &indio_dev->channels[bit],
378caa8ce7fSGwendal Grignou 						     &val);
379caa8ce7fSGwendal Grignou 		if (ret)
380caa8ce7fSGwendal Grignou 			goto out;
381caa8ce7fSGwendal Grignou 
382caa8ce7fSGwendal Grignou 		data->buffer.channels[i++] = val;
383caa8ce7fSGwendal Grignou 	}
384caa8ce7fSGwendal Grignou 
385caa8ce7fSGwendal Grignou 	iio_push_to_buffers_with_timestamp(indio_dev, &data->buffer,
386caa8ce7fSGwendal Grignou 					   pf->timestamp);
387caa8ce7fSGwendal Grignou 
388caa8ce7fSGwendal Grignou out:
389caa8ce7fSGwendal Grignou 	mutex_unlock(&data->mutex);
390caa8ce7fSGwendal Grignou 
391caa8ce7fSGwendal Grignou 	iio_trigger_notify_done(indio_dev->trig);
392caa8ce7fSGwendal Grignou 
393caa8ce7fSGwendal Grignou 	return IRQ_HANDLED;
394caa8ce7fSGwendal Grignou }
395caa8ce7fSGwendal Grignou 
396caa8ce7fSGwendal Grignou static int sx_common_buffer_preenable(struct iio_dev *indio_dev)
397caa8ce7fSGwendal Grignou {
398caa8ce7fSGwendal Grignou 	struct sx_common_data *data = iio_priv(indio_dev);
399caa8ce7fSGwendal Grignou 	unsigned long channels = 0;
400caa8ce7fSGwendal Grignou 	int bit, ret;
401caa8ce7fSGwendal Grignou 
402caa8ce7fSGwendal Grignou 	mutex_lock(&data->mutex);
403caa8ce7fSGwendal Grignou 	for_each_set_bit(bit, indio_dev->active_scan_mask,
404caa8ce7fSGwendal Grignou 			 indio_dev->masklength)
405caa8ce7fSGwendal Grignou 		__set_bit(indio_dev->channels[bit].channel, &channels);
406caa8ce7fSGwendal Grignou 
407caa8ce7fSGwendal Grignou 	ret = sx_common_update_chan_en(data, channels, data->chan_event);
408caa8ce7fSGwendal Grignou 	mutex_unlock(&data->mutex);
409caa8ce7fSGwendal Grignou 	return ret;
410caa8ce7fSGwendal Grignou }
411caa8ce7fSGwendal Grignou 
412caa8ce7fSGwendal Grignou static int sx_common_buffer_postdisable(struct iio_dev *indio_dev)
413caa8ce7fSGwendal Grignou {
414caa8ce7fSGwendal Grignou 	struct sx_common_data *data = iio_priv(indio_dev);
415caa8ce7fSGwendal Grignou 	int ret;
416caa8ce7fSGwendal Grignou 
417caa8ce7fSGwendal Grignou 	mutex_lock(&data->mutex);
418caa8ce7fSGwendal Grignou 	ret = sx_common_update_chan_en(data, 0, data->chan_event);
419caa8ce7fSGwendal Grignou 	mutex_unlock(&data->mutex);
420caa8ce7fSGwendal Grignou 	return ret;
421caa8ce7fSGwendal Grignou }
422caa8ce7fSGwendal Grignou 
423caa8ce7fSGwendal Grignou static const struct iio_buffer_setup_ops sx_common_buffer_setup_ops = {
424caa8ce7fSGwendal Grignou 	.preenable = sx_common_buffer_preenable,
425caa8ce7fSGwendal Grignou 	.postdisable = sx_common_buffer_postdisable,
426caa8ce7fSGwendal Grignou };
427caa8ce7fSGwendal Grignou 
428caa8ce7fSGwendal Grignou static void sx_common_regulator_disable(void *_data)
429caa8ce7fSGwendal Grignou {
430caa8ce7fSGwendal Grignou 	struct sx_common_data *data = _data;
431caa8ce7fSGwendal Grignou 
432caa8ce7fSGwendal Grignou 	regulator_bulk_disable(ARRAY_SIZE(data->supplies), data->supplies);
433caa8ce7fSGwendal Grignou }
434caa8ce7fSGwendal Grignou 
435caa8ce7fSGwendal Grignou #define SX_COMMON_SOFT_RESET				0xde
436caa8ce7fSGwendal Grignou 
437*7008f35cSAndy Shevchenko static int sx_common_init_device(struct device *dev, struct iio_dev *indio_dev)
438caa8ce7fSGwendal Grignou {
439caa8ce7fSGwendal Grignou 	struct sx_common_data *data = iio_priv(indio_dev);
440caa8ce7fSGwendal Grignou 	struct sx_common_reg_default tmp;
441caa8ce7fSGwendal Grignou 	const struct sx_common_reg_default *initval;
442caa8ce7fSGwendal Grignou 	int ret;
443caa8ce7fSGwendal Grignou 	unsigned int i, val;
444caa8ce7fSGwendal Grignou 
445caa8ce7fSGwendal Grignou 	ret = regmap_write(data->regmap, data->chip_info->reg_reset,
446caa8ce7fSGwendal Grignou 			   SX_COMMON_SOFT_RESET);
447caa8ce7fSGwendal Grignou 	if (ret)
448caa8ce7fSGwendal Grignou 		return ret;
449caa8ce7fSGwendal Grignou 
450caa8ce7fSGwendal Grignou 	usleep_range(1000, 2000); /* power-up time is ~1ms. */
451caa8ce7fSGwendal Grignou 
452caa8ce7fSGwendal Grignou 	/* Clear reset interrupt state by reading SX_COMMON_REG_IRQ_SRC. */
453caa8ce7fSGwendal Grignou 	ret = regmap_read(data->regmap, SX_COMMON_REG_IRQ_SRC, &val);
454caa8ce7fSGwendal Grignou 	if (ret)
455caa8ce7fSGwendal Grignou 		return ret;
456caa8ce7fSGwendal Grignou 
457caa8ce7fSGwendal Grignou 	/* Program defaults from constant or BIOS. */
458caa8ce7fSGwendal Grignou 	for (i = 0; i < data->chip_info->num_default_regs; i++) {
459*7008f35cSAndy Shevchenko 		initval = data->chip_info->ops.get_default_reg(dev, i, &tmp);
460caa8ce7fSGwendal Grignou 		ret = regmap_write(data->regmap, initval->reg, initval->def);
461caa8ce7fSGwendal Grignou 		if (ret)
462caa8ce7fSGwendal Grignou 			return ret;
463caa8ce7fSGwendal Grignou 	}
464caa8ce7fSGwendal Grignou 
465caa8ce7fSGwendal Grignou 	return data->chip_info->ops.init_compensation(indio_dev);
466caa8ce7fSGwendal Grignou }
467caa8ce7fSGwendal Grignou 
468caa8ce7fSGwendal Grignou /**
469caa8ce7fSGwendal Grignou  * sx_common_probe() - Common setup for Semtech SAR sensor
470caa8ce7fSGwendal Grignou  * @client:		I2C client object
471caa8ce7fSGwendal Grignou  * @chip_info:		Semtech sensor chip information.
472caa8ce7fSGwendal Grignou  * @regmap_config:	Sensor registers map configuration.
473caa8ce7fSGwendal Grignou  */
474caa8ce7fSGwendal Grignou int sx_common_probe(struct i2c_client *client,
475caa8ce7fSGwendal Grignou 		    const struct sx_common_chip_info *chip_info,
476caa8ce7fSGwendal Grignou 		    const struct regmap_config *regmap_config)
477caa8ce7fSGwendal Grignou {
478caa8ce7fSGwendal Grignou 	struct device *dev = &client->dev;
479caa8ce7fSGwendal Grignou 	struct iio_dev *indio_dev;
480caa8ce7fSGwendal Grignou 	struct sx_common_data *data;
481caa8ce7fSGwendal Grignou 	int ret;
482caa8ce7fSGwendal Grignou 
483caa8ce7fSGwendal Grignou 	indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
484caa8ce7fSGwendal Grignou 	if (!indio_dev)
485caa8ce7fSGwendal Grignou 		return -ENOMEM;
486caa8ce7fSGwendal Grignou 
487caa8ce7fSGwendal Grignou 	data = iio_priv(indio_dev);
488caa8ce7fSGwendal Grignou 
489caa8ce7fSGwendal Grignou 	data->chip_info = chip_info;
490caa8ce7fSGwendal Grignou 	data->client = client;
491caa8ce7fSGwendal Grignou 	data->supplies[0].supply = "vdd";
492caa8ce7fSGwendal Grignou 	data->supplies[1].supply = "svdd";
493caa8ce7fSGwendal Grignou 	mutex_init(&data->mutex);
494caa8ce7fSGwendal Grignou 	init_completion(&data->completion);
495caa8ce7fSGwendal Grignou 
496caa8ce7fSGwendal Grignou 	data->regmap = devm_regmap_init_i2c(client, regmap_config);
497caa8ce7fSGwendal Grignou 	if (IS_ERR(data->regmap))
498caa8ce7fSGwendal Grignou 		return dev_err_probe(dev, PTR_ERR(data->regmap),
499caa8ce7fSGwendal Grignou 				     "Could init register map\n");
500caa8ce7fSGwendal Grignou 
501caa8ce7fSGwendal Grignou 	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(data->supplies),
502caa8ce7fSGwendal Grignou 				      data->supplies);
503caa8ce7fSGwendal Grignou 	if (ret)
504caa8ce7fSGwendal Grignou 		return dev_err_probe(dev, ret, "Unable to get regulators\n");
505caa8ce7fSGwendal Grignou 
506caa8ce7fSGwendal Grignou 	ret = regulator_bulk_enable(ARRAY_SIZE(data->supplies), data->supplies);
507caa8ce7fSGwendal Grignou 	if (ret)
508caa8ce7fSGwendal Grignou 		return dev_err_probe(dev, ret, "Unable to enable regulators\n");
509caa8ce7fSGwendal Grignou 
510caa8ce7fSGwendal Grignou 	/* Must wait for Tpor time after initial power up */
511caa8ce7fSGwendal Grignou 	usleep_range(1000, 1100);
512caa8ce7fSGwendal Grignou 
513caa8ce7fSGwendal Grignou 	ret = devm_add_action_or_reset(dev, sx_common_regulator_disable, data);
514caa8ce7fSGwendal Grignou 	if (ret)
515caa8ce7fSGwendal Grignou 		return dev_err_probe(dev, ret,
516caa8ce7fSGwendal Grignou 				     "Unable to register regulators deleter\n");
517caa8ce7fSGwendal Grignou 
518caa8ce7fSGwendal Grignou 	ret = data->chip_info->ops.check_whoami(dev, indio_dev);
519caa8ce7fSGwendal Grignou 	if (ret)
520caa8ce7fSGwendal Grignou 		return dev_err_probe(dev, ret, "error reading WHOAMI\n");
521caa8ce7fSGwendal Grignou 
522caa8ce7fSGwendal Grignou 	ACPI_COMPANION_SET(&indio_dev->dev, ACPI_COMPANION(dev));
52374a53a95SStephen Boyd 	indio_dev->dev.of_node = client->dev.of_node;
524caa8ce7fSGwendal Grignou 	indio_dev->modes = INDIO_DIRECT_MODE;
525caa8ce7fSGwendal Grignou 
526caa8ce7fSGwendal Grignou 	indio_dev->channels =  data->chip_info->iio_channels;
527caa8ce7fSGwendal Grignou 	indio_dev->num_channels = data->chip_info->num_iio_channels;
528caa8ce7fSGwendal Grignou 	indio_dev->info = &data->chip_info->iio_info;
529caa8ce7fSGwendal Grignou 
530caa8ce7fSGwendal Grignou 	i2c_set_clientdata(client, indio_dev);
531caa8ce7fSGwendal Grignou 
532*7008f35cSAndy Shevchenko 	ret = sx_common_init_device(dev, indio_dev);
533caa8ce7fSGwendal Grignou 	if (ret)
534caa8ce7fSGwendal Grignou 		return dev_err_probe(dev, ret, "Unable to initialize sensor\n");
535caa8ce7fSGwendal Grignou 
536caa8ce7fSGwendal Grignou 	if (client->irq) {
537caa8ce7fSGwendal Grignou 		ret = devm_request_threaded_irq(dev, client->irq,
538caa8ce7fSGwendal Grignou 						sx_common_irq_handler,
539caa8ce7fSGwendal Grignou 						sx_common_irq_thread_handler,
540caa8ce7fSGwendal Grignou 						IRQF_ONESHOT,
541caa8ce7fSGwendal Grignou 						"sx_event", indio_dev);
542caa8ce7fSGwendal Grignou 		if (ret)
543caa8ce7fSGwendal Grignou 			return dev_err_probe(dev, ret, "No IRQ\n");
544caa8ce7fSGwendal Grignou 
545caa8ce7fSGwendal Grignou 		data->trig = devm_iio_trigger_alloc(dev, "%s-dev%d",
546caa8ce7fSGwendal Grignou 						    indio_dev->name,
547caa8ce7fSGwendal Grignou 						    iio_device_id(indio_dev));
548caa8ce7fSGwendal Grignou 		if (!data->trig)
549caa8ce7fSGwendal Grignou 			return -ENOMEM;
550caa8ce7fSGwendal Grignou 
551caa8ce7fSGwendal Grignou 		data->trig->ops = &sx_common_trigger_ops;
552caa8ce7fSGwendal Grignou 		iio_trigger_set_drvdata(data->trig, indio_dev);
553caa8ce7fSGwendal Grignou 
554caa8ce7fSGwendal Grignou 		ret = devm_iio_trigger_register(dev, data->trig);
555caa8ce7fSGwendal Grignou 		if (ret)
556caa8ce7fSGwendal Grignou 			return ret;
557caa8ce7fSGwendal Grignou 	}
558caa8ce7fSGwendal Grignou 
559caa8ce7fSGwendal Grignou 	ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
560caa8ce7fSGwendal Grignou 					      iio_pollfunc_store_time,
561caa8ce7fSGwendal Grignou 					      sx_common_trigger_handler,
562caa8ce7fSGwendal Grignou 					      &sx_common_buffer_setup_ops);
563caa8ce7fSGwendal Grignou 	if (ret)
564caa8ce7fSGwendal Grignou 		return ret;
565caa8ce7fSGwendal Grignou 
566caa8ce7fSGwendal Grignou 	return devm_iio_device_register(dev, indio_dev);
567caa8ce7fSGwendal Grignou }
568caa8ce7fSGwendal Grignou EXPORT_SYMBOL_NS_GPL(sx_common_probe, SEMTECH_PROX);
569caa8ce7fSGwendal Grignou 
570caa8ce7fSGwendal Grignou MODULE_AUTHOR("Gwendal Grignou <gwendal@chromium.org>");
571caa8ce7fSGwendal Grignou MODULE_DESCRIPTION("Common functions and structures for Semtech sensor");
572caa8ce7fSGwendal Grignou MODULE_LICENSE("GPL v2");
573