xref: /openbmc/linux/drivers/iio/proximity/srf08.c (revision 038b0fac)
136edc939SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
278f83902SAndreas Klinger /*
3c5bf4a04SAndreas Klinger  * srf08.c - Support for Devantech SRFxx ultrasonic ranger
4c5bf4a04SAndreas Klinger  *           with i2c interface
5dc2696baSAndreas Klinger  * actually supported are srf02, srf08, srf10
678f83902SAndreas Klinger  *
7dc2696baSAndreas Klinger  * Copyright (c) 2016, 2017 Andreas Klinger <ak@it-klinger.de>
878f83902SAndreas Klinger  *
978f83902SAndreas Klinger  * For details about the device see:
103593cd53SAlexander A. Klimov  * https://www.robot-electronics.co.uk/htm/srf08tech.html
113593cd53SAlexander A. Klimov  * https://www.robot-electronics.co.uk/htm/srf10tech.htm
123593cd53SAlexander A. Klimov  * https://www.robot-electronics.co.uk/htm/srf02tech.htm
1378f83902SAndreas Klinger  */
1478f83902SAndreas Klinger 
1578f83902SAndreas Klinger #include <linux/err.h>
1678f83902SAndreas Klinger #include <linux/i2c.h>
1778f83902SAndreas Klinger #include <linux/delay.h>
1878f83902SAndreas Klinger #include <linux/module.h>
1978f83902SAndreas Klinger #include <linux/bitops.h>
2078f83902SAndreas Klinger #include <linux/iio/iio.h>
2178f83902SAndreas Klinger #include <linux/iio/sysfs.h>
22a8319593SAndreas Klinger #include <linux/iio/buffer.h>
23a8319593SAndreas Klinger #include <linux/iio/trigger_consumer.h>
24a8319593SAndreas Klinger #include <linux/iio/triggered_buffer.h>
2578f83902SAndreas Klinger 
2678f83902SAndreas Klinger /* registers of SRF08 device */
2778f83902SAndreas Klinger #define SRF08_WRITE_COMMAND	0x00	/* Command Register */
2878f83902SAndreas Klinger #define SRF08_WRITE_MAX_GAIN	0x01	/* Max Gain Register: 0 .. 31 */
2978f83902SAndreas Klinger #define SRF08_WRITE_RANGE	0x02	/* Range Register: 0 .. 255 */
3078f83902SAndreas Klinger #define SRF08_READ_SW_REVISION	0x00	/* Software Revision */
3178f83902SAndreas Klinger #define SRF08_READ_LIGHT	0x01	/* Light Sensor during last echo */
3278f83902SAndreas Klinger #define SRF08_READ_ECHO_1_HIGH	0x02	/* Range of first echo received */
3378f83902SAndreas Klinger #define SRF08_READ_ECHO_1_LOW	0x03	/* Range of first echo received */
3478f83902SAndreas Klinger 
3578f83902SAndreas Klinger #define SRF08_CMD_RANGING_CM	0x51	/* Ranging Mode - Result in cm */
3678f83902SAndreas Klinger 
37c5bf4a04SAndreas Klinger enum srf08_sensor_type {
38dc2696baSAndreas Klinger 	SRF02,
39c5bf4a04SAndreas Klinger 	SRF08,
40c5bf4a04SAndreas Klinger 	SRF10,
41c5bf4a04SAndreas Klinger 	SRF_MAX_TYPE
42c5bf4a04SAndreas Klinger };
43c5bf4a04SAndreas Klinger 
44c5bf4a04SAndreas Klinger struct srf08_chip_info {
45c5bf4a04SAndreas Klinger 	const int		*sensitivity_avail;
46c5bf4a04SAndreas Klinger 	int			num_sensitivity_avail;
47c5bf4a04SAndreas Klinger 	int			sensitivity_default;
48dc2696baSAndreas Klinger 
49dc2696baSAndreas Klinger 	/* default value of Range in mm */
50dc2696baSAndreas Klinger 	int			range_default;
51c5bf4a04SAndreas Klinger };
52c5bf4a04SAndreas Klinger 
5378f83902SAndreas Klinger struct srf08_data {
5478f83902SAndreas Klinger 	struct i2c_client	*client;
55a8319593SAndreas Klinger 
56a8319593SAndreas Klinger 	/*
57a8319593SAndreas Klinger 	 * Gain in the datasheet is called sensitivity here to distinct it
58a8319593SAndreas Klinger 	 * from the gain used with amplifiers of adc's
59a8319593SAndreas Klinger 	 */
60a8319593SAndreas Klinger 	int			sensitivity;
61a8319593SAndreas Klinger 
62a8319593SAndreas Klinger 	/* max. Range in mm */
63a8319593SAndreas Klinger 	int			range_mm;
6478f83902SAndreas Klinger 	struct mutex		lock;
65a8319593SAndreas Klinger 
6619f1a254SJonathan Cameron 	/* Ensure timestamp is naturally aligned */
6719f1a254SJonathan Cameron 	struct {
6819f1a254SJonathan Cameron 		s16 chan;
6919f1a254SJonathan Cameron 		s64 timestamp __aligned(8);
7019f1a254SJonathan Cameron 	} scan;
71c5bf4a04SAndreas Klinger 
72c5bf4a04SAndreas Klinger 	/* Sensor-Type */
73c5bf4a04SAndreas Klinger 	enum srf08_sensor_type	sensor_type;
74c5bf4a04SAndreas Klinger 
75c5bf4a04SAndreas Klinger 	/* Chip-specific information */
76c5bf4a04SAndreas Klinger 	const struct srf08_chip_info	*chip_info;
7778f83902SAndreas Klinger };
7878f83902SAndreas Klinger 
7978f83902SAndreas Klinger /*
8078f83902SAndreas Klinger  * in the documentation one can read about the "Gain" of the device
8178f83902SAndreas Klinger  * which is used here for amplifying the signal and filtering out unwanted
8278f83902SAndreas Klinger  * ones.
8378f83902SAndreas Klinger  * But with ADC's this term is already used differently and that's why it
8478f83902SAndreas Klinger  * is called "Sensitivity" here.
8578f83902SAndreas Klinger  */
86dc2696baSAndreas Klinger static const struct srf08_chip_info srf02_chip_info = {
87dc2696baSAndreas Klinger 	.sensitivity_avail	= NULL,
88dc2696baSAndreas Klinger 	.num_sensitivity_avail	= 0,
89dc2696baSAndreas Klinger 	.sensitivity_default	= 0,
90dc2696baSAndreas Klinger 
91dc2696baSAndreas Klinger 	.range_default		= 0,
92dc2696baSAndreas Klinger };
93dc2696baSAndreas Klinger 
94c5bf4a04SAndreas Klinger static const int srf08_sensitivity_avail[] = {
9578f83902SAndreas Klinger 	 94,  97, 100, 103, 107, 110, 114, 118,
9678f83902SAndreas Klinger 	123, 128, 133, 139, 145, 152, 159, 168,
9778f83902SAndreas Klinger 	177, 187, 199, 212, 227, 245, 265, 288,
98c5bf4a04SAndreas Klinger 	317, 352, 395, 450, 524, 626, 777, 1025
99c5bf4a04SAndreas Klinger 	};
100c5bf4a04SAndreas Klinger 
101c5bf4a04SAndreas Klinger static const struct srf08_chip_info srf08_chip_info = {
102c5bf4a04SAndreas Klinger 	.sensitivity_avail	= srf08_sensitivity_avail,
103c5bf4a04SAndreas Klinger 	.num_sensitivity_avail	= ARRAY_SIZE(srf08_sensitivity_avail),
104c5bf4a04SAndreas Klinger 	.sensitivity_default	= 1025,
105dc2696baSAndreas Klinger 
106dc2696baSAndreas Klinger 	.range_default		= 6020,
107c5bf4a04SAndreas Klinger };
108c5bf4a04SAndreas Klinger 
109c5bf4a04SAndreas Klinger static const int srf10_sensitivity_avail[] = {
110c5bf4a04SAndreas Klinger 	 40,  40,  50,  60,  70,  80, 100, 120,
111c5bf4a04SAndreas Klinger 	140, 200, 250, 300, 350, 400, 500, 600,
112c5bf4a04SAndreas Klinger 	700,
113c5bf4a04SAndreas Klinger 	};
114c5bf4a04SAndreas Klinger 
115c5bf4a04SAndreas Klinger static const struct srf08_chip_info srf10_chip_info = {
116c5bf4a04SAndreas Klinger 	.sensitivity_avail	= srf10_sensitivity_avail,
117c5bf4a04SAndreas Klinger 	.num_sensitivity_avail	= ARRAY_SIZE(srf10_sensitivity_avail),
118c5bf4a04SAndreas Klinger 	.sensitivity_default	= 700,
119dc2696baSAndreas Klinger 
120dc2696baSAndreas Klinger 	.range_default		= 6020,
121c5bf4a04SAndreas Klinger };
12278f83902SAndreas Klinger 
12378f83902SAndreas Klinger static int srf08_read_ranging(struct srf08_data *data)
12478f83902SAndreas Klinger {
12578f83902SAndreas Klinger 	struct i2c_client *client = data->client;
12678f83902SAndreas Klinger 	int ret, i;
12778f83902SAndreas Klinger 	int waittime;
12878f83902SAndreas Klinger 
12978f83902SAndreas Klinger 	mutex_lock(&data->lock);
13078f83902SAndreas Klinger 
13178f83902SAndreas Klinger 	ret = i2c_smbus_write_byte_data(data->client,
13278f83902SAndreas Klinger 			SRF08_WRITE_COMMAND, SRF08_CMD_RANGING_CM);
13378f83902SAndreas Klinger 	if (ret < 0) {
13478f83902SAndreas Klinger 		dev_err(&client->dev, "write command - err: %d\n", ret);
13578f83902SAndreas Klinger 		mutex_unlock(&data->lock);
13678f83902SAndreas Klinger 		return ret;
13778f83902SAndreas Klinger 	}
13878f83902SAndreas Klinger 
13978f83902SAndreas Klinger 	/*
14078f83902SAndreas Klinger 	 * we read here until a correct version number shows up as
14178f83902SAndreas Klinger 	 * suggested by the documentation
14278f83902SAndreas Klinger 	 *
14378f83902SAndreas Klinger 	 * with an ultrasonic speed of 343 m/s and a roundtrip of it
14478f83902SAndreas Klinger 	 * sleep the expected duration and try to read from the device
14578f83902SAndreas Klinger 	 * if nothing useful is read try it in a shorter grid
14678f83902SAndreas Klinger 	 *
14778f83902SAndreas Klinger 	 * polling for not more than 20 ms should be enough
14878f83902SAndreas Klinger 	 */
14978f83902SAndreas Klinger 	waittime = 1 + data->range_mm / 172;
15078f83902SAndreas Klinger 	msleep(waittime);
15178f83902SAndreas Klinger 	for (i = 0; i < 4; i++) {
15278f83902SAndreas Klinger 		ret = i2c_smbus_read_byte_data(data->client,
15378f83902SAndreas Klinger 						SRF08_READ_SW_REVISION);
15478f83902SAndreas Klinger 
15578f83902SAndreas Klinger 		/* check if a valid version number is read */
15678f83902SAndreas Klinger 		if (ret < 255 && ret > 0)
15778f83902SAndreas Klinger 			break;
15878f83902SAndreas Klinger 		msleep(5);
15978f83902SAndreas Klinger 	}
16078f83902SAndreas Klinger 
16178f83902SAndreas Klinger 	if (ret >= 255 || ret <= 0) {
16278f83902SAndreas Klinger 		dev_err(&client->dev, "device not ready\n");
16378f83902SAndreas Klinger 		mutex_unlock(&data->lock);
16478f83902SAndreas Klinger 		return -EIO;
16578f83902SAndreas Klinger 	}
16678f83902SAndreas Klinger 
16778f83902SAndreas Klinger 	ret = i2c_smbus_read_word_swapped(data->client,
16878f83902SAndreas Klinger 						SRF08_READ_ECHO_1_HIGH);
16978f83902SAndreas Klinger 	if (ret < 0) {
17078f83902SAndreas Klinger 		dev_err(&client->dev, "cannot read distance: ret=%d\n", ret);
17178f83902SAndreas Klinger 		mutex_unlock(&data->lock);
17278f83902SAndreas Klinger 		return ret;
17378f83902SAndreas Klinger 	}
17478f83902SAndreas Klinger 
17578f83902SAndreas Klinger 	mutex_unlock(&data->lock);
17678f83902SAndreas Klinger 
17778f83902SAndreas Klinger 	return ret;
17878f83902SAndreas Klinger }
17978f83902SAndreas Klinger 
180a8319593SAndreas Klinger static irqreturn_t srf08_trigger_handler(int irq, void *p)
181a8319593SAndreas Klinger {
182a8319593SAndreas Klinger 	struct iio_poll_func *pf = p;
183a8319593SAndreas Klinger 	struct iio_dev *indio_dev = pf->indio_dev;
184a8319593SAndreas Klinger 	struct srf08_data *data = iio_priv(indio_dev);
185a8319593SAndreas Klinger 	s16 sensor_data;
186a8319593SAndreas Klinger 
187a8319593SAndreas Klinger 	sensor_data = srf08_read_ranging(data);
188a8319593SAndreas Klinger 	if (sensor_data < 0)
189a8319593SAndreas Klinger 		goto err;
190a8319593SAndreas Klinger 
191a8319593SAndreas Klinger 	mutex_lock(&data->lock);
192a8319593SAndreas Klinger 
19319f1a254SJonathan Cameron 	data->scan.chan = sensor_data;
194a8319593SAndreas Klinger 	iio_push_to_buffers_with_timestamp(indio_dev,
19519f1a254SJonathan Cameron 					   &data->scan, pf->timestamp);
196a8319593SAndreas Klinger 
197a8319593SAndreas Klinger 	mutex_unlock(&data->lock);
198a8319593SAndreas Klinger err:
199a8319593SAndreas Klinger 	iio_trigger_notify_done(indio_dev->trig);
200a8319593SAndreas Klinger 	return IRQ_HANDLED;
201a8319593SAndreas Klinger }
202a8319593SAndreas Klinger 
20378f83902SAndreas Klinger static int srf08_read_raw(struct iio_dev *indio_dev,
20478f83902SAndreas Klinger 			    struct iio_chan_spec const *channel, int *val,
20578f83902SAndreas Klinger 			    int *val2, long mask)
20678f83902SAndreas Klinger {
20778f83902SAndreas Klinger 	struct srf08_data *data = iio_priv(indio_dev);
20878f83902SAndreas Klinger 	int ret;
20978f83902SAndreas Klinger 
21078f83902SAndreas Klinger 	if (channel->type != IIO_DISTANCE)
21178f83902SAndreas Klinger 		return -EINVAL;
21278f83902SAndreas Klinger 
21378f83902SAndreas Klinger 	switch (mask) {
21478f83902SAndreas Klinger 	case IIO_CHAN_INFO_RAW:
21578f83902SAndreas Klinger 		ret = srf08_read_ranging(data);
21678f83902SAndreas Klinger 		if (ret < 0)
21778f83902SAndreas Klinger 			return ret;
21878f83902SAndreas Klinger 		*val = ret;
21978f83902SAndreas Klinger 		return IIO_VAL_INT;
22078f83902SAndreas Klinger 	case IIO_CHAN_INFO_SCALE:
22178f83902SAndreas Klinger 		/* 1 LSB is 1 cm */
22278f83902SAndreas Klinger 		*val = 0;
22378f83902SAndreas Klinger 		*val2 = 10000;
22478f83902SAndreas Klinger 		return IIO_VAL_INT_PLUS_MICRO;
22578f83902SAndreas Klinger 	default:
22678f83902SAndreas Klinger 		return -EINVAL;
22778f83902SAndreas Klinger 	}
22878f83902SAndreas Klinger }
22978f83902SAndreas Klinger 
23078f83902SAndreas Klinger static ssize_t srf08_show_range_mm_available(struct device *dev,
23178f83902SAndreas Klinger 				struct device_attribute *attr, char *buf)
23278f83902SAndreas Klinger {
23378f83902SAndreas Klinger 	return sprintf(buf, "[0.043 0.043 11.008]\n");
23478f83902SAndreas Klinger }
23578f83902SAndreas Klinger 
23678f83902SAndreas Klinger static IIO_DEVICE_ATTR(sensor_max_range_available, S_IRUGO,
23778f83902SAndreas Klinger 				srf08_show_range_mm_available, NULL, 0);
23878f83902SAndreas Klinger 
23978f83902SAndreas Klinger static ssize_t srf08_show_range_mm(struct device *dev,
24078f83902SAndreas Klinger 				struct device_attribute *attr, char *buf)
24178f83902SAndreas Klinger {
24278f83902SAndreas Klinger 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
24378f83902SAndreas Klinger 	struct srf08_data *data = iio_priv(indio_dev);
24478f83902SAndreas Klinger 
24578f83902SAndreas Klinger 	return sprintf(buf, "%d.%03d\n", data->range_mm / 1000,
24678f83902SAndreas Klinger 						data->range_mm % 1000);
24778f83902SAndreas Klinger }
24878f83902SAndreas Klinger 
24978f83902SAndreas Klinger /*
25078f83902SAndreas Klinger  * set the range of the sensor to an even multiple of 43 mm
25178f83902SAndreas Klinger  * which corresponds to 1 LSB in the register
25278f83902SAndreas Klinger  *
25378f83902SAndreas Klinger  * register value    corresponding range
25478f83902SAndreas Klinger  *         0x00             43 mm
25578f83902SAndreas Klinger  *         0x01             86 mm
25678f83902SAndreas Klinger  *         0x02            129 mm
25778f83902SAndreas Klinger  *         ...
25878f83902SAndreas Klinger  *         0xFF          11008 mm
25978f83902SAndreas Klinger  */
26078f83902SAndreas Klinger static ssize_t srf08_write_range_mm(struct srf08_data *data, unsigned int val)
26178f83902SAndreas Klinger {
26278f83902SAndreas Klinger 	int ret;
26378f83902SAndreas Klinger 	struct i2c_client *client = data->client;
26478f83902SAndreas Klinger 	unsigned int mod;
26578f83902SAndreas Klinger 	u8 regval;
26678f83902SAndreas Klinger 
26778f83902SAndreas Klinger 	ret = val / 43 - 1;
26878f83902SAndreas Klinger 	mod = val % 43;
26978f83902SAndreas Klinger 
27078f83902SAndreas Klinger 	if (mod || (ret < 0) || (ret > 255))
27178f83902SAndreas Klinger 		return -EINVAL;
27278f83902SAndreas Klinger 
27378f83902SAndreas Klinger 	regval = ret;
27478f83902SAndreas Klinger 
27578f83902SAndreas Klinger 	mutex_lock(&data->lock);
27678f83902SAndreas Klinger 
27778f83902SAndreas Klinger 	ret = i2c_smbus_write_byte_data(client, SRF08_WRITE_RANGE, regval);
27878f83902SAndreas Klinger 	if (ret < 0) {
27978f83902SAndreas Klinger 		dev_err(&client->dev, "write_range - err: %d\n", ret);
28078f83902SAndreas Klinger 		mutex_unlock(&data->lock);
28178f83902SAndreas Klinger 		return ret;
28278f83902SAndreas Klinger 	}
28378f83902SAndreas Klinger 
28478f83902SAndreas Klinger 	data->range_mm = val;
28578f83902SAndreas Klinger 
28678f83902SAndreas Klinger 	mutex_unlock(&data->lock);
28778f83902SAndreas Klinger 
28878f83902SAndreas Klinger 	return 0;
28978f83902SAndreas Klinger }
29078f83902SAndreas Klinger 
29178f83902SAndreas Klinger static ssize_t srf08_store_range_mm(struct device *dev,
29278f83902SAndreas Klinger 					struct device_attribute *attr,
29378f83902SAndreas Klinger 					const char *buf, size_t len)
29478f83902SAndreas Klinger {
29578f83902SAndreas Klinger 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
29678f83902SAndreas Klinger 	struct srf08_data *data = iio_priv(indio_dev);
29778f83902SAndreas Klinger 	int ret;
29878f83902SAndreas Klinger 	int integer, fract;
29978f83902SAndreas Klinger 
30078f83902SAndreas Klinger 	ret = iio_str_to_fixpoint(buf, 100, &integer, &fract);
30178f83902SAndreas Klinger 	if (ret)
30278f83902SAndreas Klinger 		return ret;
30378f83902SAndreas Klinger 
30478f83902SAndreas Klinger 	ret = srf08_write_range_mm(data, integer * 1000 + fract);
30578f83902SAndreas Klinger 	if (ret < 0)
30678f83902SAndreas Klinger 		return ret;
30778f83902SAndreas Klinger 
30878f83902SAndreas Klinger 	return len;
30978f83902SAndreas Klinger }
31078f83902SAndreas Klinger 
31178f83902SAndreas Klinger static IIO_DEVICE_ATTR(sensor_max_range, S_IRUGO | S_IWUSR,
31278f83902SAndreas Klinger 			srf08_show_range_mm, srf08_store_range_mm, 0);
31378f83902SAndreas Klinger 
31478f83902SAndreas Klinger static ssize_t srf08_show_sensitivity_available(struct device *dev,
31578f83902SAndreas Klinger 				struct device_attribute *attr, char *buf)
31678f83902SAndreas Klinger {
31778f83902SAndreas Klinger 	int i, len = 0;
318c5bf4a04SAndreas Klinger 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
319c5bf4a04SAndreas Klinger 	struct srf08_data *data = iio_priv(indio_dev);
32078f83902SAndreas Klinger 
321c5bf4a04SAndreas Klinger 	for (i = 0; i < data->chip_info->num_sensitivity_avail; i++)
322c5bf4a04SAndreas Klinger 		if (data->chip_info->sensitivity_avail[i])
323c5bf4a04SAndreas Klinger 			len += sprintf(buf + len, "%d ",
324c5bf4a04SAndreas Klinger 				data->chip_info->sensitivity_avail[i]);
32578f83902SAndreas Klinger 
32678f83902SAndreas Klinger 	len += sprintf(buf + len, "\n");
32778f83902SAndreas Klinger 
32878f83902SAndreas Klinger 	return len;
32978f83902SAndreas Klinger }
33078f83902SAndreas Klinger 
33178f83902SAndreas Klinger static IIO_DEVICE_ATTR(sensor_sensitivity_available, S_IRUGO,
33278f83902SAndreas Klinger 				srf08_show_sensitivity_available, NULL, 0);
33378f83902SAndreas Klinger 
33478f83902SAndreas Klinger static ssize_t srf08_show_sensitivity(struct device *dev,
33578f83902SAndreas Klinger 				struct device_attribute *attr, char *buf)
33678f83902SAndreas Klinger {
33778f83902SAndreas Klinger 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
33878f83902SAndreas Klinger 	struct srf08_data *data = iio_priv(indio_dev);
33978f83902SAndreas Klinger 	int len;
34078f83902SAndreas Klinger 
34178f83902SAndreas Klinger 	len = sprintf(buf, "%d\n", data->sensitivity);
34278f83902SAndreas Klinger 
34378f83902SAndreas Klinger 	return len;
34478f83902SAndreas Klinger }
34578f83902SAndreas Klinger 
34678f83902SAndreas Klinger static ssize_t srf08_write_sensitivity(struct srf08_data *data,
34778f83902SAndreas Klinger 							unsigned int val)
34878f83902SAndreas Klinger {
34978f83902SAndreas Klinger 	struct i2c_client *client = data->client;
35078f83902SAndreas Klinger 	int ret, i;
35178f83902SAndreas Klinger 	u8 regval;
35278f83902SAndreas Klinger 
353c5bf4a04SAndreas Klinger 	if (!val)
354c5bf4a04SAndreas Klinger 		return -EINVAL;
355c5bf4a04SAndreas Klinger 
356c5bf4a04SAndreas Klinger 	for (i = 0; i < data->chip_info->num_sensitivity_avail; i++)
357574e60b3SLi Zhengyu 		if (val == data->chip_info->sensitivity_avail[i]) {
35878f83902SAndreas Klinger 			regval = i;
35978f83902SAndreas Klinger 			break;
36078f83902SAndreas Klinger 		}
36178f83902SAndreas Klinger 
362c5bf4a04SAndreas Klinger 	if (i >= data->chip_info->num_sensitivity_avail)
36378f83902SAndreas Klinger 		return -EINVAL;
36478f83902SAndreas Klinger 
36578f83902SAndreas Klinger 	mutex_lock(&data->lock);
36678f83902SAndreas Klinger 
367c5bf4a04SAndreas Klinger 	ret = i2c_smbus_write_byte_data(client, SRF08_WRITE_MAX_GAIN, regval);
36878f83902SAndreas Klinger 	if (ret < 0) {
36978f83902SAndreas Klinger 		dev_err(&client->dev, "write_sensitivity - err: %d\n", ret);
37078f83902SAndreas Klinger 		mutex_unlock(&data->lock);
37178f83902SAndreas Klinger 		return ret;
37278f83902SAndreas Klinger 	}
37378f83902SAndreas Klinger 
37478f83902SAndreas Klinger 	data->sensitivity = val;
37578f83902SAndreas Klinger 
37678f83902SAndreas Klinger 	mutex_unlock(&data->lock);
37778f83902SAndreas Klinger 
37878f83902SAndreas Klinger 	return 0;
37978f83902SAndreas Klinger }
38078f83902SAndreas Klinger 
38178f83902SAndreas Klinger static ssize_t srf08_store_sensitivity(struct device *dev,
38278f83902SAndreas Klinger 						struct device_attribute *attr,
38378f83902SAndreas Klinger 						const char *buf, size_t len)
38478f83902SAndreas Klinger {
38578f83902SAndreas Klinger 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
38678f83902SAndreas Klinger 	struct srf08_data *data = iio_priv(indio_dev);
38778f83902SAndreas Klinger 	int ret;
38878f83902SAndreas Klinger 	unsigned int val;
38978f83902SAndreas Klinger 
39078f83902SAndreas Klinger 	ret = kstrtouint(buf, 10, &val);
39178f83902SAndreas Klinger 	if (ret)
39278f83902SAndreas Klinger 		return ret;
39378f83902SAndreas Klinger 
39478f83902SAndreas Klinger 	ret = srf08_write_sensitivity(data, val);
39578f83902SAndreas Klinger 	if (ret < 0)
39678f83902SAndreas Klinger 		return ret;
39778f83902SAndreas Klinger 
39878f83902SAndreas Klinger 	return len;
39978f83902SAndreas Klinger }
40078f83902SAndreas Klinger 
40178f83902SAndreas Klinger static IIO_DEVICE_ATTR(sensor_sensitivity, S_IRUGO | S_IWUSR,
40278f83902SAndreas Klinger 			srf08_show_sensitivity, srf08_store_sensitivity, 0);
40378f83902SAndreas Klinger 
40478f83902SAndreas Klinger static struct attribute *srf08_attributes[] = {
40578f83902SAndreas Klinger 	&iio_dev_attr_sensor_max_range.dev_attr.attr,
40678f83902SAndreas Klinger 	&iio_dev_attr_sensor_max_range_available.dev_attr.attr,
40778f83902SAndreas Klinger 	&iio_dev_attr_sensor_sensitivity.dev_attr.attr,
40878f83902SAndreas Klinger 	&iio_dev_attr_sensor_sensitivity_available.dev_attr.attr,
40978f83902SAndreas Klinger 	NULL,
41078f83902SAndreas Klinger };
41178f83902SAndreas Klinger 
41278f83902SAndreas Klinger static const struct attribute_group srf08_attribute_group = {
41378f83902SAndreas Klinger 	.attrs = srf08_attributes,
41478f83902SAndreas Klinger };
41578f83902SAndreas Klinger 
41678f83902SAndreas Klinger static const struct iio_chan_spec srf08_channels[] = {
41778f83902SAndreas Klinger 	{
41878f83902SAndreas Klinger 		.type = IIO_DISTANCE,
41978f83902SAndreas Klinger 		.info_mask_separate =
42078f83902SAndreas Klinger 				BIT(IIO_CHAN_INFO_RAW) |
42178f83902SAndreas Klinger 				BIT(IIO_CHAN_INFO_SCALE),
422a8319593SAndreas Klinger 		.scan_index = 0,
423a8319593SAndreas Klinger 		.scan_type = {
424a8319593SAndreas Klinger 			.sign = 's',
425a8319593SAndreas Klinger 			.realbits = 16,
426a8319593SAndreas Klinger 			.storagebits = 16,
427a8319593SAndreas Klinger 			.endianness = IIO_CPU,
42878f83902SAndreas Klinger 		},
429a8319593SAndreas Klinger 	},
430a8319593SAndreas Klinger 	IIO_CHAN_SOFT_TIMESTAMP(1),
43178f83902SAndreas Klinger };
43278f83902SAndreas Klinger 
43378f83902SAndreas Klinger static const struct iio_info srf08_info = {
43478f83902SAndreas Klinger 	.read_raw = srf08_read_raw,
43578f83902SAndreas Klinger 	.attrs = &srf08_attribute_group,
43678f83902SAndreas Klinger };
43778f83902SAndreas Klinger 
438dc2696baSAndreas Klinger /*
439dc2696baSAndreas Klinger  * srf02 don't have an adjustable range or sensitivity,
440dc2696baSAndreas Klinger  * so we don't need attributes at all
441dc2696baSAndreas Klinger  */
442dc2696baSAndreas Klinger static const struct iio_info srf02_info = {
443dc2696baSAndreas Klinger 	.read_raw = srf08_read_raw,
444dc2696baSAndreas Klinger };
445dc2696baSAndreas Klinger 
446*038b0facSUwe Kleine-König static int srf08_probe(struct i2c_client *client)
44778f83902SAndreas Klinger {
448*038b0facSUwe Kleine-König 	const struct i2c_device_id *id = i2c_client_get_device_id(client);
44978f83902SAndreas Klinger 	struct iio_dev *indio_dev;
45078f83902SAndreas Klinger 	struct srf08_data *data;
45178f83902SAndreas Klinger 	int ret;
45278f83902SAndreas Klinger 
45378f83902SAndreas Klinger 	if (!i2c_check_functionality(client->adapter,
45478f83902SAndreas Klinger 					I2C_FUNC_SMBUS_READ_BYTE_DATA |
45578f83902SAndreas Klinger 					I2C_FUNC_SMBUS_WRITE_BYTE_DATA |
45678f83902SAndreas Klinger 					I2C_FUNC_SMBUS_READ_WORD_DATA))
45778f83902SAndreas Klinger 		return -ENODEV;
45878f83902SAndreas Klinger 
45978f83902SAndreas Klinger 	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
46078f83902SAndreas Klinger 	if (!indio_dev)
46178f83902SAndreas Klinger 		return -ENOMEM;
46278f83902SAndreas Klinger 
46378f83902SAndreas Klinger 	data = iio_priv(indio_dev);
46478f83902SAndreas Klinger 	i2c_set_clientdata(client, indio_dev);
46578f83902SAndreas Klinger 	data->client = client;
466c5bf4a04SAndreas Klinger 	data->sensor_type = (enum srf08_sensor_type)id->driver_data;
46778f83902SAndreas Klinger 
468c5bf4a04SAndreas Klinger 	switch (data->sensor_type) {
469dc2696baSAndreas Klinger 	case SRF02:
470dc2696baSAndreas Klinger 		data->chip_info = &srf02_chip_info;
471dc2696baSAndreas Klinger 		indio_dev->info = &srf02_info;
472dc2696baSAndreas Klinger 		break;
473c5bf4a04SAndreas Klinger 	case SRF08:
474c5bf4a04SAndreas Klinger 		data->chip_info = &srf08_chip_info;
475dc2696baSAndreas Klinger 		indio_dev->info = &srf08_info;
476c5bf4a04SAndreas Klinger 		break;
477c5bf4a04SAndreas Klinger 	case SRF10:
478c5bf4a04SAndreas Klinger 		data->chip_info = &srf10_chip_info;
479dc2696baSAndreas Klinger 		indio_dev->info = &srf08_info;
480c5bf4a04SAndreas Klinger 		break;
481c5bf4a04SAndreas Klinger 	default:
482c5bf4a04SAndreas Klinger 		return -EINVAL;
483c5bf4a04SAndreas Klinger 	}
484c5bf4a04SAndreas Klinger 
485c5bf4a04SAndreas Klinger 	indio_dev->name = id->name;
48678f83902SAndreas Klinger 	indio_dev->modes = INDIO_DIRECT_MODE;
48778f83902SAndreas Klinger 	indio_dev->channels = srf08_channels;
48878f83902SAndreas Klinger 	indio_dev->num_channels = ARRAY_SIZE(srf08_channels);
48978f83902SAndreas Klinger 
49078f83902SAndreas Klinger 	mutex_init(&data->lock);
49178f83902SAndreas Klinger 
492a8319593SAndreas Klinger 	ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev,
493a8319593SAndreas Klinger 			iio_pollfunc_store_time, srf08_trigger_handler, NULL);
494a8319593SAndreas Klinger 	if (ret < 0) {
495a8319593SAndreas Klinger 		dev_err(&client->dev, "setup of iio triggered buffer failed\n");
496a8319593SAndreas Klinger 		return ret;
497a8319593SAndreas Klinger 	}
498a8319593SAndreas Klinger 
499dc2696baSAndreas Klinger 	if (data->chip_info->range_default) {
50078f83902SAndreas Klinger 		/*
501dc2696baSAndreas Klinger 		 * set default range of device in mm here
50278f83902SAndreas Klinger 		 * these register values cannot be read from the hardware
50378f83902SAndreas Klinger 		 * therefore set driver specific default values
504dc2696baSAndreas Klinger 		 *
505dc2696baSAndreas Klinger 		 * srf02 don't have a default value so it'll be omitted
50678f83902SAndreas Klinger 		 */
507dc2696baSAndreas Klinger 		ret = srf08_write_range_mm(data,
508dc2696baSAndreas Klinger 					data->chip_info->range_default);
50978f83902SAndreas Klinger 		if (ret < 0)
51078f83902SAndreas Klinger 			return ret;
511dc2696baSAndreas Klinger 	}
51278f83902SAndreas Klinger 
513dc2696baSAndreas Klinger 	if (data->chip_info->sensitivity_default) {
514dc2696baSAndreas Klinger 		/*
515dc2696baSAndreas Klinger 		 * set default sensitivity of device here
516dc2696baSAndreas Klinger 		 * these register values cannot be read from the hardware
517dc2696baSAndreas Klinger 		 * therefore set driver specific default values
518dc2696baSAndreas Klinger 		 *
519dc2696baSAndreas Klinger 		 * srf02 don't have a default value so it'll be omitted
520dc2696baSAndreas Klinger 		 */
521c5bf4a04SAndreas Klinger 		ret = srf08_write_sensitivity(data,
522c5bf4a04SAndreas Klinger 				data->chip_info->sensitivity_default);
52378f83902SAndreas Klinger 		if (ret < 0)
52478f83902SAndreas Klinger 			return ret;
525dc2696baSAndreas Klinger 	}
52678f83902SAndreas Klinger 
52778f83902SAndreas Klinger 	return devm_iio_device_register(&client->dev, indio_dev);
52878f83902SAndreas Klinger }
52978f83902SAndreas Klinger 
530c02b3a11SAndreas Klinger static const struct of_device_id of_srf08_match[] = {
531dc2696baSAndreas Klinger 	{ .compatible = "devantech,srf02", (void *)SRF02 },
532c5bf4a04SAndreas Klinger 	{ .compatible = "devantech,srf08", (void *)SRF08 },
533c5bf4a04SAndreas Klinger 	{ .compatible = "devantech,srf10", (void *)SRF10 },
534c02b3a11SAndreas Klinger 	{},
535c02b3a11SAndreas Klinger };
536c02b3a11SAndreas Klinger 
537c02b3a11SAndreas Klinger MODULE_DEVICE_TABLE(of, of_srf08_match);
538c02b3a11SAndreas Klinger 
53978f83902SAndreas Klinger static const struct i2c_device_id srf08_id[] = {
540dc2696baSAndreas Klinger 	{ "srf02", SRF02 },
541c5bf4a04SAndreas Klinger 	{ "srf08", SRF08 },
542c5bf4a04SAndreas Klinger 	{ "srf10", SRF10 },
54378f83902SAndreas Klinger 	{ }
54478f83902SAndreas Klinger };
54578f83902SAndreas Klinger MODULE_DEVICE_TABLE(i2c, srf08_id);
54678f83902SAndreas Klinger 
54778f83902SAndreas Klinger static struct i2c_driver srf08_driver = {
54878f83902SAndreas Klinger 	.driver = {
54978f83902SAndreas Klinger 		.name	= "srf08",
550c02b3a11SAndreas Klinger 		.of_match_table	= of_srf08_match,
55178f83902SAndreas Klinger 	},
552*038b0facSUwe Kleine-König 	.probe_new = srf08_probe,
55378f83902SAndreas Klinger 	.id_table = srf08_id,
55478f83902SAndreas Klinger };
55578f83902SAndreas Klinger module_i2c_driver(srf08_driver);
55678f83902SAndreas Klinger 
55778f83902SAndreas Klinger MODULE_AUTHOR("Andreas Klinger <ak@it-klinger.de>");
558dc2696baSAndreas Klinger MODULE_DESCRIPTION("Devantech SRF02/SRF08/SRF10 i2c ultrasonic ranger driver");
55978f83902SAndreas Klinger MODULE_LICENSE("GPL");
560