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