xref: /OK3568_Linux_fs/kernel/drivers/iio/proximity/srf08.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * srf08.c - Support for Devantech SRFxx ultrasonic ranger
4*4882a593Smuzhiyun  *           with i2c interface
5*4882a593Smuzhiyun  * actually supported are srf02, srf08, srf10
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Copyright (c) 2016, 2017 Andreas Klinger <ak@it-klinger.de>
8*4882a593Smuzhiyun  *
9*4882a593Smuzhiyun  * For details about the device see:
10*4882a593Smuzhiyun  * https://www.robot-electronics.co.uk/htm/srf08tech.html
11*4882a593Smuzhiyun  * https://www.robot-electronics.co.uk/htm/srf10tech.htm
12*4882a593Smuzhiyun  * https://www.robot-electronics.co.uk/htm/srf02tech.htm
13*4882a593Smuzhiyun  */
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun #include <linux/err.h>
16*4882a593Smuzhiyun #include <linux/i2c.h>
17*4882a593Smuzhiyun #include <linux/delay.h>
18*4882a593Smuzhiyun #include <linux/module.h>
19*4882a593Smuzhiyun #include <linux/bitops.h>
20*4882a593Smuzhiyun #include <linux/iio/iio.h>
21*4882a593Smuzhiyun #include <linux/iio/sysfs.h>
22*4882a593Smuzhiyun #include <linux/iio/buffer.h>
23*4882a593Smuzhiyun #include <linux/iio/trigger_consumer.h>
24*4882a593Smuzhiyun #include <linux/iio/triggered_buffer.h>
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun /* registers of SRF08 device */
27*4882a593Smuzhiyun #define SRF08_WRITE_COMMAND	0x00	/* Command Register */
28*4882a593Smuzhiyun #define SRF08_WRITE_MAX_GAIN	0x01	/* Max Gain Register: 0 .. 31 */
29*4882a593Smuzhiyun #define SRF08_WRITE_RANGE	0x02	/* Range Register: 0 .. 255 */
30*4882a593Smuzhiyun #define SRF08_READ_SW_REVISION	0x00	/* Software Revision */
31*4882a593Smuzhiyun #define SRF08_READ_LIGHT	0x01	/* Light Sensor during last echo */
32*4882a593Smuzhiyun #define SRF08_READ_ECHO_1_HIGH	0x02	/* Range of first echo received */
33*4882a593Smuzhiyun #define SRF08_READ_ECHO_1_LOW	0x03	/* Range of first echo received */
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun #define SRF08_CMD_RANGING_CM	0x51	/* Ranging Mode - Result in cm */
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun enum srf08_sensor_type {
38*4882a593Smuzhiyun 	SRF02,
39*4882a593Smuzhiyun 	SRF08,
40*4882a593Smuzhiyun 	SRF10,
41*4882a593Smuzhiyun 	SRF_MAX_TYPE
42*4882a593Smuzhiyun };
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun struct srf08_chip_info {
45*4882a593Smuzhiyun 	const int		*sensitivity_avail;
46*4882a593Smuzhiyun 	int			num_sensitivity_avail;
47*4882a593Smuzhiyun 	int			sensitivity_default;
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun 	/* default value of Range in mm */
50*4882a593Smuzhiyun 	int			range_default;
51*4882a593Smuzhiyun };
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun struct srf08_data {
54*4882a593Smuzhiyun 	struct i2c_client	*client;
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun 	/*
57*4882a593Smuzhiyun 	 * Gain in the datasheet is called sensitivity here to distinct it
58*4882a593Smuzhiyun 	 * from the gain used with amplifiers of adc's
59*4882a593Smuzhiyun 	 */
60*4882a593Smuzhiyun 	int			sensitivity;
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun 	/* max. Range in mm */
63*4882a593Smuzhiyun 	int			range_mm;
64*4882a593Smuzhiyun 	struct mutex		lock;
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun 	/* Ensure timestamp is naturally aligned */
67*4882a593Smuzhiyun 	struct {
68*4882a593Smuzhiyun 		s16 chan;
69*4882a593Smuzhiyun 		s64 timestamp __aligned(8);
70*4882a593Smuzhiyun 	} scan;
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 	/* Sensor-Type */
73*4882a593Smuzhiyun 	enum srf08_sensor_type	sensor_type;
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun 	/* Chip-specific information */
76*4882a593Smuzhiyun 	const struct srf08_chip_info	*chip_info;
77*4882a593Smuzhiyun };
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun /*
80*4882a593Smuzhiyun  * in the documentation one can read about the "Gain" of the device
81*4882a593Smuzhiyun  * which is used here for amplifying the signal and filtering out unwanted
82*4882a593Smuzhiyun  * ones.
83*4882a593Smuzhiyun  * But with ADC's this term is already used differently and that's why it
84*4882a593Smuzhiyun  * is called "Sensitivity" here.
85*4882a593Smuzhiyun  */
86*4882a593Smuzhiyun static const struct srf08_chip_info srf02_chip_info = {
87*4882a593Smuzhiyun 	.sensitivity_avail	= NULL,
88*4882a593Smuzhiyun 	.num_sensitivity_avail	= 0,
89*4882a593Smuzhiyun 	.sensitivity_default	= 0,
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun 	.range_default		= 0,
92*4882a593Smuzhiyun };
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun static const int srf08_sensitivity_avail[] = {
95*4882a593Smuzhiyun 	 94,  97, 100, 103, 107, 110, 114, 118,
96*4882a593Smuzhiyun 	123, 128, 133, 139, 145, 152, 159, 168,
97*4882a593Smuzhiyun 	177, 187, 199, 212, 227, 245, 265, 288,
98*4882a593Smuzhiyun 	317, 352, 395, 450, 524, 626, 777, 1025
99*4882a593Smuzhiyun 	};
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun static const struct srf08_chip_info srf08_chip_info = {
102*4882a593Smuzhiyun 	.sensitivity_avail	= srf08_sensitivity_avail,
103*4882a593Smuzhiyun 	.num_sensitivity_avail	= ARRAY_SIZE(srf08_sensitivity_avail),
104*4882a593Smuzhiyun 	.sensitivity_default	= 1025,
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 	.range_default		= 6020,
107*4882a593Smuzhiyun };
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun static const int srf10_sensitivity_avail[] = {
110*4882a593Smuzhiyun 	 40,  40,  50,  60,  70,  80, 100, 120,
111*4882a593Smuzhiyun 	140, 200, 250, 300, 350, 400, 500, 600,
112*4882a593Smuzhiyun 	700,
113*4882a593Smuzhiyun 	};
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun static const struct srf08_chip_info srf10_chip_info = {
116*4882a593Smuzhiyun 	.sensitivity_avail	= srf10_sensitivity_avail,
117*4882a593Smuzhiyun 	.num_sensitivity_avail	= ARRAY_SIZE(srf10_sensitivity_avail),
118*4882a593Smuzhiyun 	.sensitivity_default	= 700,
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	.range_default		= 6020,
121*4882a593Smuzhiyun };
122*4882a593Smuzhiyun 
srf08_read_ranging(struct srf08_data * data)123*4882a593Smuzhiyun static int srf08_read_ranging(struct srf08_data *data)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun 	struct i2c_client *client = data->client;
126*4882a593Smuzhiyun 	int ret, i;
127*4882a593Smuzhiyun 	int waittime;
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun 	mutex_lock(&data->lock);
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	ret = i2c_smbus_write_byte_data(data->client,
132*4882a593Smuzhiyun 			SRF08_WRITE_COMMAND, SRF08_CMD_RANGING_CM);
133*4882a593Smuzhiyun 	if (ret < 0) {
134*4882a593Smuzhiyun 		dev_err(&client->dev, "write command - err: %d\n", ret);
135*4882a593Smuzhiyun 		mutex_unlock(&data->lock);
136*4882a593Smuzhiyun 		return ret;
137*4882a593Smuzhiyun 	}
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	/*
140*4882a593Smuzhiyun 	 * we read here until a correct version number shows up as
141*4882a593Smuzhiyun 	 * suggested by the documentation
142*4882a593Smuzhiyun 	 *
143*4882a593Smuzhiyun 	 * with an ultrasonic speed of 343 m/s and a roundtrip of it
144*4882a593Smuzhiyun 	 * sleep the expected duration and try to read from the device
145*4882a593Smuzhiyun 	 * if nothing useful is read try it in a shorter grid
146*4882a593Smuzhiyun 	 *
147*4882a593Smuzhiyun 	 * polling for not more than 20 ms should be enough
148*4882a593Smuzhiyun 	 */
149*4882a593Smuzhiyun 	waittime = 1 + data->range_mm / 172;
150*4882a593Smuzhiyun 	msleep(waittime);
151*4882a593Smuzhiyun 	for (i = 0; i < 4; i++) {
152*4882a593Smuzhiyun 		ret = i2c_smbus_read_byte_data(data->client,
153*4882a593Smuzhiyun 						SRF08_READ_SW_REVISION);
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 		/* check if a valid version number is read */
156*4882a593Smuzhiyun 		if (ret < 255 && ret > 0)
157*4882a593Smuzhiyun 			break;
158*4882a593Smuzhiyun 		msleep(5);
159*4882a593Smuzhiyun 	}
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 	if (ret >= 255 || ret <= 0) {
162*4882a593Smuzhiyun 		dev_err(&client->dev, "device not ready\n");
163*4882a593Smuzhiyun 		mutex_unlock(&data->lock);
164*4882a593Smuzhiyun 		return -EIO;
165*4882a593Smuzhiyun 	}
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 	ret = i2c_smbus_read_word_swapped(data->client,
168*4882a593Smuzhiyun 						SRF08_READ_ECHO_1_HIGH);
169*4882a593Smuzhiyun 	if (ret < 0) {
170*4882a593Smuzhiyun 		dev_err(&client->dev, "cannot read distance: ret=%d\n", ret);
171*4882a593Smuzhiyun 		mutex_unlock(&data->lock);
172*4882a593Smuzhiyun 		return ret;
173*4882a593Smuzhiyun 	}
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 	mutex_unlock(&data->lock);
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun 	return ret;
178*4882a593Smuzhiyun }
179*4882a593Smuzhiyun 
srf08_trigger_handler(int irq,void * p)180*4882a593Smuzhiyun static irqreturn_t srf08_trigger_handler(int irq, void *p)
181*4882a593Smuzhiyun {
182*4882a593Smuzhiyun 	struct iio_poll_func *pf = p;
183*4882a593Smuzhiyun 	struct iio_dev *indio_dev = pf->indio_dev;
184*4882a593Smuzhiyun 	struct srf08_data *data = iio_priv(indio_dev);
185*4882a593Smuzhiyun 	s16 sensor_data;
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun 	sensor_data = srf08_read_ranging(data);
188*4882a593Smuzhiyun 	if (sensor_data < 0)
189*4882a593Smuzhiyun 		goto err;
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun 	mutex_lock(&data->lock);
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 	data->scan.chan = sensor_data;
194*4882a593Smuzhiyun 	iio_push_to_buffers_with_timestamp(indio_dev,
195*4882a593Smuzhiyun 					   &data->scan, pf->timestamp);
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	mutex_unlock(&data->lock);
198*4882a593Smuzhiyun err:
199*4882a593Smuzhiyun 	iio_trigger_notify_done(indio_dev->trig);
200*4882a593Smuzhiyun 	return IRQ_HANDLED;
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun 
srf08_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * channel,int * val,int * val2,long mask)203*4882a593Smuzhiyun static int srf08_read_raw(struct iio_dev *indio_dev,
204*4882a593Smuzhiyun 			    struct iio_chan_spec const *channel, int *val,
205*4882a593Smuzhiyun 			    int *val2, long mask)
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun 	struct srf08_data *data = iio_priv(indio_dev);
208*4882a593Smuzhiyun 	int ret;
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 	if (channel->type != IIO_DISTANCE)
211*4882a593Smuzhiyun 		return -EINVAL;
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun 	switch (mask) {
214*4882a593Smuzhiyun 	case IIO_CHAN_INFO_RAW:
215*4882a593Smuzhiyun 		ret = srf08_read_ranging(data);
216*4882a593Smuzhiyun 		if (ret < 0)
217*4882a593Smuzhiyun 			return ret;
218*4882a593Smuzhiyun 		*val = ret;
219*4882a593Smuzhiyun 		return IIO_VAL_INT;
220*4882a593Smuzhiyun 	case IIO_CHAN_INFO_SCALE:
221*4882a593Smuzhiyun 		/* 1 LSB is 1 cm */
222*4882a593Smuzhiyun 		*val = 0;
223*4882a593Smuzhiyun 		*val2 = 10000;
224*4882a593Smuzhiyun 		return IIO_VAL_INT_PLUS_MICRO;
225*4882a593Smuzhiyun 	default:
226*4882a593Smuzhiyun 		return -EINVAL;
227*4882a593Smuzhiyun 	}
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun 
srf08_show_range_mm_available(struct device * dev,struct device_attribute * attr,char * buf)230*4882a593Smuzhiyun static ssize_t srf08_show_range_mm_available(struct device *dev,
231*4882a593Smuzhiyun 				struct device_attribute *attr, char *buf)
232*4882a593Smuzhiyun {
233*4882a593Smuzhiyun 	return sprintf(buf, "[0.043 0.043 11.008]\n");
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun static IIO_DEVICE_ATTR(sensor_max_range_available, S_IRUGO,
237*4882a593Smuzhiyun 				srf08_show_range_mm_available, NULL, 0);
238*4882a593Smuzhiyun 
srf08_show_range_mm(struct device * dev,struct device_attribute * attr,char * buf)239*4882a593Smuzhiyun static ssize_t srf08_show_range_mm(struct device *dev,
240*4882a593Smuzhiyun 				struct device_attribute *attr, char *buf)
241*4882a593Smuzhiyun {
242*4882a593Smuzhiyun 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
243*4882a593Smuzhiyun 	struct srf08_data *data = iio_priv(indio_dev);
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun 	return sprintf(buf, "%d.%03d\n", data->range_mm / 1000,
246*4882a593Smuzhiyun 						data->range_mm % 1000);
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun /*
250*4882a593Smuzhiyun  * set the range of the sensor to an even multiple of 43 mm
251*4882a593Smuzhiyun  * which corresponds to 1 LSB in the register
252*4882a593Smuzhiyun  *
253*4882a593Smuzhiyun  * register value    corresponding range
254*4882a593Smuzhiyun  *         0x00             43 mm
255*4882a593Smuzhiyun  *         0x01             86 mm
256*4882a593Smuzhiyun  *         0x02            129 mm
257*4882a593Smuzhiyun  *         ...
258*4882a593Smuzhiyun  *         0xFF          11008 mm
259*4882a593Smuzhiyun  */
srf08_write_range_mm(struct srf08_data * data,unsigned int val)260*4882a593Smuzhiyun static ssize_t srf08_write_range_mm(struct srf08_data *data, unsigned int val)
261*4882a593Smuzhiyun {
262*4882a593Smuzhiyun 	int ret;
263*4882a593Smuzhiyun 	struct i2c_client *client = data->client;
264*4882a593Smuzhiyun 	unsigned int mod;
265*4882a593Smuzhiyun 	u8 regval;
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	ret = val / 43 - 1;
268*4882a593Smuzhiyun 	mod = val % 43;
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun 	if (mod || (ret < 0) || (ret > 255))
271*4882a593Smuzhiyun 		return -EINVAL;
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 	regval = ret;
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun 	mutex_lock(&data->lock);
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun 	ret = i2c_smbus_write_byte_data(client, SRF08_WRITE_RANGE, regval);
278*4882a593Smuzhiyun 	if (ret < 0) {
279*4882a593Smuzhiyun 		dev_err(&client->dev, "write_range - err: %d\n", ret);
280*4882a593Smuzhiyun 		mutex_unlock(&data->lock);
281*4882a593Smuzhiyun 		return ret;
282*4882a593Smuzhiyun 	}
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun 	data->range_mm = val;
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun 	mutex_unlock(&data->lock);
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun 	return 0;
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun 
srf08_store_range_mm(struct device * dev,struct device_attribute * attr,const char * buf,size_t len)291*4882a593Smuzhiyun static ssize_t srf08_store_range_mm(struct device *dev,
292*4882a593Smuzhiyun 					struct device_attribute *attr,
293*4882a593Smuzhiyun 					const char *buf, size_t len)
294*4882a593Smuzhiyun {
295*4882a593Smuzhiyun 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
296*4882a593Smuzhiyun 	struct srf08_data *data = iio_priv(indio_dev);
297*4882a593Smuzhiyun 	int ret;
298*4882a593Smuzhiyun 	int integer, fract;
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 	ret = iio_str_to_fixpoint(buf, 100, &integer, &fract);
301*4882a593Smuzhiyun 	if (ret)
302*4882a593Smuzhiyun 		return ret;
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun 	ret = srf08_write_range_mm(data, integer * 1000 + fract);
305*4882a593Smuzhiyun 	if (ret < 0)
306*4882a593Smuzhiyun 		return ret;
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	return len;
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun static IIO_DEVICE_ATTR(sensor_max_range, S_IRUGO | S_IWUSR,
312*4882a593Smuzhiyun 			srf08_show_range_mm, srf08_store_range_mm, 0);
313*4882a593Smuzhiyun 
srf08_show_sensitivity_available(struct device * dev,struct device_attribute * attr,char * buf)314*4882a593Smuzhiyun static ssize_t srf08_show_sensitivity_available(struct device *dev,
315*4882a593Smuzhiyun 				struct device_attribute *attr, char *buf)
316*4882a593Smuzhiyun {
317*4882a593Smuzhiyun 	int i, len = 0;
318*4882a593Smuzhiyun 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
319*4882a593Smuzhiyun 	struct srf08_data *data = iio_priv(indio_dev);
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun 	for (i = 0; i < data->chip_info->num_sensitivity_avail; i++)
322*4882a593Smuzhiyun 		if (data->chip_info->sensitivity_avail[i])
323*4882a593Smuzhiyun 			len += sprintf(buf + len, "%d ",
324*4882a593Smuzhiyun 				data->chip_info->sensitivity_avail[i]);
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	len += sprintf(buf + len, "\n");
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun 	return len;
329*4882a593Smuzhiyun }
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun static IIO_DEVICE_ATTR(sensor_sensitivity_available, S_IRUGO,
332*4882a593Smuzhiyun 				srf08_show_sensitivity_available, NULL, 0);
333*4882a593Smuzhiyun 
srf08_show_sensitivity(struct device * dev,struct device_attribute * attr,char * buf)334*4882a593Smuzhiyun static ssize_t srf08_show_sensitivity(struct device *dev,
335*4882a593Smuzhiyun 				struct device_attribute *attr, char *buf)
336*4882a593Smuzhiyun {
337*4882a593Smuzhiyun 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
338*4882a593Smuzhiyun 	struct srf08_data *data = iio_priv(indio_dev);
339*4882a593Smuzhiyun 	int len;
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun 	len = sprintf(buf, "%d\n", data->sensitivity);
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	return len;
344*4882a593Smuzhiyun }
345*4882a593Smuzhiyun 
srf08_write_sensitivity(struct srf08_data * data,unsigned int val)346*4882a593Smuzhiyun static ssize_t srf08_write_sensitivity(struct srf08_data *data,
347*4882a593Smuzhiyun 							unsigned int val)
348*4882a593Smuzhiyun {
349*4882a593Smuzhiyun 	struct i2c_client *client = data->client;
350*4882a593Smuzhiyun 	int ret, i;
351*4882a593Smuzhiyun 	u8 regval;
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun 	if (!val)
354*4882a593Smuzhiyun 		return -EINVAL;
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun 	for (i = 0; i < data->chip_info->num_sensitivity_avail; i++)
357*4882a593Smuzhiyun 		if (val && (val == data->chip_info->sensitivity_avail[i])) {
358*4882a593Smuzhiyun 			regval = i;
359*4882a593Smuzhiyun 			break;
360*4882a593Smuzhiyun 		}
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun 	if (i >= data->chip_info->num_sensitivity_avail)
363*4882a593Smuzhiyun 		return -EINVAL;
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun 	mutex_lock(&data->lock);
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun 	ret = i2c_smbus_write_byte_data(client, SRF08_WRITE_MAX_GAIN, regval);
368*4882a593Smuzhiyun 	if (ret < 0) {
369*4882a593Smuzhiyun 		dev_err(&client->dev, "write_sensitivity - err: %d\n", ret);
370*4882a593Smuzhiyun 		mutex_unlock(&data->lock);
371*4882a593Smuzhiyun 		return ret;
372*4882a593Smuzhiyun 	}
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun 	data->sensitivity = val;
375*4882a593Smuzhiyun 
376*4882a593Smuzhiyun 	mutex_unlock(&data->lock);
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun 	return 0;
379*4882a593Smuzhiyun }
380*4882a593Smuzhiyun 
srf08_store_sensitivity(struct device * dev,struct device_attribute * attr,const char * buf,size_t len)381*4882a593Smuzhiyun static ssize_t srf08_store_sensitivity(struct device *dev,
382*4882a593Smuzhiyun 						struct device_attribute *attr,
383*4882a593Smuzhiyun 						const char *buf, size_t len)
384*4882a593Smuzhiyun {
385*4882a593Smuzhiyun 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
386*4882a593Smuzhiyun 	struct srf08_data *data = iio_priv(indio_dev);
387*4882a593Smuzhiyun 	int ret;
388*4882a593Smuzhiyun 	unsigned int val;
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun 	ret = kstrtouint(buf, 10, &val);
391*4882a593Smuzhiyun 	if (ret)
392*4882a593Smuzhiyun 		return ret;
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun 	ret = srf08_write_sensitivity(data, val);
395*4882a593Smuzhiyun 	if (ret < 0)
396*4882a593Smuzhiyun 		return ret;
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun 	return len;
399*4882a593Smuzhiyun }
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun static IIO_DEVICE_ATTR(sensor_sensitivity, S_IRUGO | S_IWUSR,
402*4882a593Smuzhiyun 			srf08_show_sensitivity, srf08_store_sensitivity, 0);
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun static struct attribute *srf08_attributes[] = {
405*4882a593Smuzhiyun 	&iio_dev_attr_sensor_max_range.dev_attr.attr,
406*4882a593Smuzhiyun 	&iio_dev_attr_sensor_max_range_available.dev_attr.attr,
407*4882a593Smuzhiyun 	&iio_dev_attr_sensor_sensitivity.dev_attr.attr,
408*4882a593Smuzhiyun 	&iio_dev_attr_sensor_sensitivity_available.dev_attr.attr,
409*4882a593Smuzhiyun 	NULL,
410*4882a593Smuzhiyun };
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun static const struct attribute_group srf08_attribute_group = {
413*4882a593Smuzhiyun 	.attrs = srf08_attributes,
414*4882a593Smuzhiyun };
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun static const struct iio_chan_spec srf08_channels[] = {
417*4882a593Smuzhiyun 	{
418*4882a593Smuzhiyun 		.type = IIO_DISTANCE,
419*4882a593Smuzhiyun 		.info_mask_separate =
420*4882a593Smuzhiyun 				BIT(IIO_CHAN_INFO_RAW) |
421*4882a593Smuzhiyun 				BIT(IIO_CHAN_INFO_SCALE),
422*4882a593Smuzhiyun 		.scan_index = 0,
423*4882a593Smuzhiyun 		.scan_type = {
424*4882a593Smuzhiyun 			.sign = 's',
425*4882a593Smuzhiyun 			.realbits = 16,
426*4882a593Smuzhiyun 			.storagebits = 16,
427*4882a593Smuzhiyun 			.endianness = IIO_CPU,
428*4882a593Smuzhiyun 		},
429*4882a593Smuzhiyun 	},
430*4882a593Smuzhiyun 	IIO_CHAN_SOFT_TIMESTAMP(1),
431*4882a593Smuzhiyun };
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun static const struct iio_info srf08_info = {
434*4882a593Smuzhiyun 	.read_raw = srf08_read_raw,
435*4882a593Smuzhiyun 	.attrs = &srf08_attribute_group,
436*4882a593Smuzhiyun };
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun /*
439*4882a593Smuzhiyun  * srf02 don't have an adjustable range or sensitivity,
440*4882a593Smuzhiyun  * so we don't need attributes at all
441*4882a593Smuzhiyun  */
442*4882a593Smuzhiyun static const struct iio_info srf02_info = {
443*4882a593Smuzhiyun 	.read_raw = srf08_read_raw,
444*4882a593Smuzhiyun };
445*4882a593Smuzhiyun 
srf08_probe(struct i2c_client * client,const struct i2c_device_id * id)446*4882a593Smuzhiyun static int srf08_probe(struct i2c_client *client,
447*4882a593Smuzhiyun 					 const struct i2c_device_id *id)
448*4882a593Smuzhiyun {
449*4882a593Smuzhiyun 	struct iio_dev *indio_dev;
450*4882a593Smuzhiyun 	struct srf08_data *data;
451*4882a593Smuzhiyun 	int ret;
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun 	if (!i2c_check_functionality(client->adapter,
454*4882a593Smuzhiyun 					I2C_FUNC_SMBUS_READ_BYTE_DATA |
455*4882a593Smuzhiyun 					I2C_FUNC_SMBUS_WRITE_BYTE_DATA |
456*4882a593Smuzhiyun 					I2C_FUNC_SMBUS_READ_WORD_DATA))
457*4882a593Smuzhiyun 		return -ENODEV;
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun 	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
460*4882a593Smuzhiyun 	if (!indio_dev)
461*4882a593Smuzhiyun 		return -ENOMEM;
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun 	data = iio_priv(indio_dev);
464*4882a593Smuzhiyun 	i2c_set_clientdata(client, indio_dev);
465*4882a593Smuzhiyun 	data->client = client;
466*4882a593Smuzhiyun 	data->sensor_type = (enum srf08_sensor_type)id->driver_data;
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun 	switch (data->sensor_type) {
469*4882a593Smuzhiyun 	case SRF02:
470*4882a593Smuzhiyun 		data->chip_info = &srf02_chip_info;
471*4882a593Smuzhiyun 		indio_dev->info = &srf02_info;
472*4882a593Smuzhiyun 		break;
473*4882a593Smuzhiyun 	case SRF08:
474*4882a593Smuzhiyun 		data->chip_info = &srf08_chip_info;
475*4882a593Smuzhiyun 		indio_dev->info = &srf08_info;
476*4882a593Smuzhiyun 		break;
477*4882a593Smuzhiyun 	case SRF10:
478*4882a593Smuzhiyun 		data->chip_info = &srf10_chip_info;
479*4882a593Smuzhiyun 		indio_dev->info = &srf08_info;
480*4882a593Smuzhiyun 		break;
481*4882a593Smuzhiyun 	default:
482*4882a593Smuzhiyun 		return -EINVAL;
483*4882a593Smuzhiyun 	}
484*4882a593Smuzhiyun 
485*4882a593Smuzhiyun 	indio_dev->name = id->name;
486*4882a593Smuzhiyun 	indio_dev->modes = INDIO_DIRECT_MODE;
487*4882a593Smuzhiyun 	indio_dev->channels = srf08_channels;
488*4882a593Smuzhiyun 	indio_dev->num_channels = ARRAY_SIZE(srf08_channels);
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun 	mutex_init(&data->lock);
491*4882a593Smuzhiyun 
492*4882a593Smuzhiyun 	ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev,
493*4882a593Smuzhiyun 			iio_pollfunc_store_time, srf08_trigger_handler, NULL);
494*4882a593Smuzhiyun 	if (ret < 0) {
495*4882a593Smuzhiyun 		dev_err(&client->dev, "setup of iio triggered buffer failed\n");
496*4882a593Smuzhiyun 		return ret;
497*4882a593Smuzhiyun 	}
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun 	if (data->chip_info->range_default) {
500*4882a593Smuzhiyun 		/*
501*4882a593Smuzhiyun 		 * set default range of device in mm here
502*4882a593Smuzhiyun 		 * these register values cannot be read from the hardware
503*4882a593Smuzhiyun 		 * therefore set driver specific default values
504*4882a593Smuzhiyun 		 *
505*4882a593Smuzhiyun 		 * srf02 don't have a default value so it'll be omitted
506*4882a593Smuzhiyun 		 */
507*4882a593Smuzhiyun 		ret = srf08_write_range_mm(data,
508*4882a593Smuzhiyun 					data->chip_info->range_default);
509*4882a593Smuzhiyun 		if (ret < 0)
510*4882a593Smuzhiyun 			return ret;
511*4882a593Smuzhiyun 	}
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun 	if (data->chip_info->sensitivity_default) {
514*4882a593Smuzhiyun 		/*
515*4882a593Smuzhiyun 		 * set default sensitivity of device here
516*4882a593Smuzhiyun 		 * these register values cannot be read from the hardware
517*4882a593Smuzhiyun 		 * therefore set driver specific default values
518*4882a593Smuzhiyun 		 *
519*4882a593Smuzhiyun 		 * srf02 don't have a default value so it'll be omitted
520*4882a593Smuzhiyun 		 */
521*4882a593Smuzhiyun 		ret = srf08_write_sensitivity(data,
522*4882a593Smuzhiyun 				data->chip_info->sensitivity_default);
523*4882a593Smuzhiyun 		if (ret < 0)
524*4882a593Smuzhiyun 			return ret;
525*4882a593Smuzhiyun 	}
526*4882a593Smuzhiyun 
527*4882a593Smuzhiyun 	return devm_iio_device_register(&client->dev, indio_dev);
528*4882a593Smuzhiyun }
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun static const struct of_device_id of_srf08_match[] = {
531*4882a593Smuzhiyun 	{ .compatible = "devantech,srf02", (void *)SRF02},
532*4882a593Smuzhiyun 	{ .compatible = "devantech,srf08", (void *)SRF08},
533*4882a593Smuzhiyun 	{ .compatible = "devantech,srf10", (void *)SRF10},
534*4882a593Smuzhiyun 	{},
535*4882a593Smuzhiyun };
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, of_srf08_match);
538*4882a593Smuzhiyun 
539*4882a593Smuzhiyun static const struct i2c_device_id srf08_id[] = {
540*4882a593Smuzhiyun 	{ "srf02", SRF02 },
541*4882a593Smuzhiyun 	{ "srf08", SRF08 },
542*4882a593Smuzhiyun 	{ "srf10", SRF10 },
543*4882a593Smuzhiyun 	{ }
544*4882a593Smuzhiyun };
545*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, srf08_id);
546*4882a593Smuzhiyun 
547*4882a593Smuzhiyun static struct i2c_driver srf08_driver = {
548*4882a593Smuzhiyun 	.driver = {
549*4882a593Smuzhiyun 		.name	= "srf08",
550*4882a593Smuzhiyun 		.of_match_table	= of_srf08_match,
551*4882a593Smuzhiyun 	},
552*4882a593Smuzhiyun 	.probe = srf08_probe,
553*4882a593Smuzhiyun 	.id_table = srf08_id,
554*4882a593Smuzhiyun };
555*4882a593Smuzhiyun module_i2c_driver(srf08_driver);
556*4882a593Smuzhiyun 
557*4882a593Smuzhiyun MODULE_AUTHOR("Andreas Klinger <ak@it-klinger.de>");
558*4882a593Smuzhiyun MODULE_DESCRIPTION("Devantech SRF02/SRF08/SRF10 i2c ultrasonic ranger driver");
559*4882a593Smuzhiyun MODULE_LICENSE("GPL");
560