xref: /openbmc/linux/drivers/iio/proximity/srf08.c (revision c5bf4a04)
178f83902SAndreas Klinger /*
2c5bf4a04SAndreas Klinger  * srf08.c - Support for Devantech SRFxx ultrasonic ranger
3c5bf4a04SAndreas Klinger  *           with i2c interface
4c5bf4a04SAndreas Klinger  * actually supported are srf08, srf10
578f83902SAndreas Klinger  *
678f83902SAndreas Klinger  * Copyright (c) 2016 Andreas Klinger <ak@it-klinger.de>
778f83902SAndreas Klinger  *
878f83902SAndreas Klinger  * This file is subject to the terms and conditions of version 2 of
978f83902SAndreas Klinger  * the GNU General Public License.  See the file COPYING in the main
1078f83902SAndreas Klinger  * directory of this archive for more details.
1178f83902SAndreas Klinger  *
1278f83902SAndreas Klinger  * For details about the device see:
1378f83902SAndreas Klinger  * http://www.robot-electronics.co.uk/htm/srf08tech.html
14c5bf4a04SAndreas Klinger  * http://www.robot-electronics.co.uk/htm/srf10tech.htm
1578f83902SAndreas Klinger  */
1678f83902SAndreas Klinger 
1778f83902SAndreas Klinger #include <linux/err.h>
1878f83902SAndreas Klinger #include <linux/i2c.h>
1978f83902SAndreas Klinger #include <linux/delay.h>
2078f83902SAndreas Klinger #include <linux/module.h>
2178f83902SAndreas Klinger #include <linux/bitops.h>
2278f83902SAndreas Klinger #include <linux/iio/iio.h>
2378f83902SAndreas Klinger #include <linux/iio/sysfs.h>
24a8319593SAndreas Klinger #include <linux/iio/buffer.h>
25a8319593SAndreas Klinger #include <linux/iio/trigger_consumer.h>
26a8319593SAndreas Klinger #include <linux/iio/triggered_buffer.h>
2778f83902SAndreas Klinger 
2878f83902SAndreas Klinger /* registers of SRF08 device */
2978f83902SAndreas Klinger #define SRF08_WRITE_COMMAND	0x00	/* Command Register */
3078f83902SAndreas Klinger #define SRF08_WRITE_MAX_GAIN	0x01	/* Max Gain Register: 0 .. 31 */
3178f83902SAndreas Klinger #define SRF08_WRITE_RANGE	0x02	/* Range Register: 0 .. 255 */
3278f83902SAndreas Klinger #define SRF08_READ_SW_REVISION	0x00	/* Software Revision */
3378f83902SAndreas Klinger #define SRF08_READ_LIGHT	0x01	/* Light Sensor during last echo */
3478f83902SAndreas Klinger #define SRF08_READ_ECHO_1_HIGH	0x02	/* Range of first echo received */
3578f83902SAndreas Klinger #define SRF08_READ_ECHO_1_LOW	0x03	/* Range of first echo received */
3678f83902SAndreas Klinger 
3778f83902SAndreas Klinger #define SRF08_CMD_RANGING_CM	0x51	/* Ranging Mode - Result in cm */
3878f83902SAndreas Klinger 
3978f83902SAndreas Klinger #define SRF08_DEFAULT_RANGE	6020	/* default value of Range in mm */
4078f83902SAndreas Klinger 
41c5bf4a04SAndreas Klinger enum srf08_sensor_type {
42c5bf4a04SAndreas Klinger 	SRF08,
43c5bf4a04SAndreas Klinger 	SRF10,
44c5bf4a04SAndreas Klinger 	SRF_MAX_TYPE
45c5bf4a04SAndreas Klinger };
46c5bf4a04SAndreas Klinger 
47c5bf4a04SAndreas Klinger struct srf08_chip_info {
48c5bf4a04SAndreas Klinger 	const int		*sensitivity_avail;
49c5bf4a04SAndreas Klinger 	int			num_sensitivity_avail;
50c5bf4a04SAndreas Klinger 	int			sensitivity_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 
66a8319593SAndreas Klinger 	/*
67a8319593SAndreas Klinger 	 * triggered buffer
68a8319593SAndreas Klinger 	 * 1x16-bit channel + 3x16 padding + 4x16 timestamp
69a8319593SAndreas Klinger 	 */
70a8319593SAndreas Klinger 	s16			buffer[8];
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  */
86c5bf4a04SAndreas Klinger static const int srf08_sensitivity_avail[] = {
8778f83902SAndreas Klinger 	 94,  97, 100, 103, 107, 110, 114, 118,
8878f83902SAndreas Klinger 	123, 128, 133, 139, 145, 152, 159, 168,
8978f83902SAndreas Klinger 	177, 187, 199, 212, 227, 245, 265, 288,
90c5bf4a04SAndreas Klinger 	317, 352, 395, 450, 524, 626, 777, 1025
91c5bf4a04SAndreas Klinger 	};
92c5bf4a04SAndreas Klinger 
93c5bf4a04SAndreas Klinger static const struct srf08_chip_info srf08_chip_info = {
94c5bf4a04SAndreas Klinger 	.sensitivity_avail	= srf08_sensitivity_avail,
95c5bf4a04SAndreas Klinger 	.num_sensitivity_avail	= ARRAY_SIZE(srf08_sensitivity_avail),
96c5bf4a04SAndreas Klinger 	.sensitivity_default	= 1025,
97c5bf4a04SAndreas Klinger };
98c5bf4a04SAndreas Klinger 
99c5bf4a04SAndreas Klinger static const int srf10_sensitivity_avail[] = {
100c5bf4a04SAndreas Klinger 	 40,  40,  50,  60,  70,  80, 100, 120,
101c5bf4a04SAndreas Klinger 	140, 200, 250, 300, 350, 400, 500, 600,
102c5bf4a04SAndreas Klinger 	700,
103c5bf4a04SAndreas Klinger 	};
104c5bf4a04SAndreas Klinger 
105c5bf4a04SAndreas Klinger static const struct srf08_chip_info srf10_chip_info = {
106c5bf4a04SAndreas Klinger 	.sensitivity_avail	= srf10_sensitivity_avail,
107c5bf4a04SAndreas Klinger 	.num_sensitivity_avail	= ARRAY_SIZE(srf10_sensitivity_avail),
108c5bf4a04SAndreas Klinger 	.sensitivity_default	= 700,
109c5bf4a04SAndreas Klinger };
11078f83902SAndreas Klinger 
11178f83902SAndreas Klinger static int srf08_read_ranging(struct srf08_data *data)
11278f83902SAndreas Klinger {
11378f83902SAndreas Klinger 	struct i2c_client *client = data->client;
11478f83902SAndreas Klinger 	int ret, i;
11578f83902SAndreas Klinger 	int waittime;
11678f83902SAndreas Klinger 
11778f83902SAndreas Klinger 	mutex_lock(&data->lock);
11878f83902SAndreas Klinger 
11978f83902SAndreas Klinger 	ret = i2c_smbus_write_byte_data(data->client,
12078f83902SAndreas Klinger 			SRF08_WRITE_COMMAND, SRF08_CMD_RANGING_CM);
12178f83902SAndreas Klinger 	if (ret < 0) {
12278f83902SAndreas Klinger 		dev_err(&client->dev, "write command - err: %d\n", ret);
12378f83902SAndreas Klinger 		mutex_unlock(&data->lock);
12478f83902SAndreas Klinger 		return ret;
12578f83902SAndreas Klinger 	}
12678f83902SAndreas Klinger 
12778f83902SAndreas Klinger 	/*
12878f83902SAndreas Klinger 	 * we read here until a correct version number shows up as
12978f83902SAndreas Klinger 	 * suggested by the documentation
13078f83902SAndreas Klinger 	 *
13178f83902SAndreas Klinger 	 * with an ultrasonic speed of 343 m/s and a roundtrip of it
13278f83902SAndreas Klinger 	 * sleep the expected duration and try to read from the device
13378f83902SAndreas Klinger 	 * if nothing useful is read try it in a shorter grid
13478f83902SAndreas Klinger 	 *
13578f83902SAndreas Klinger 	 * polling for not more than 20 ms should be enough
13678f83902SAndreas Klinger 	 */
13778f83902SAndreas Klinger 	waittime = 1 + data->range_mm / 172;
13878f83902SAndreas Klinger 	msleep(waittime);
13978f83902SAndreas Klinger 	for (i = 0; i < 4; i++) {
14078f83902SAndreas Klinger 		ret = i2c_smbus_read_byte_data(data->client,
14178f83902SAndreas Klinger 						SRF08_READ_SW_REVISION);
14278f83902SAndreas Klinger 
14378f83902SAndreas Klinger 		/* check if a valid version number is read */
14478f83902SAndreas Klinger 		if (ret < 255 && ret > 0)
14578f83902SAndreas Klinger 			break;
14678f83902SAndreas Klinger 		msleep(5);
14778f83902SAndreas Klinger 	}
14878f83902SAndreas Klinger 
14978f83902SAndreas Klinger 	if (ret >= 255 || ret <= 0) {
15078f83902SAndreas Klinger 		dev_err(&client->dev, "device not ready\n");
15178f83902SAndreas Klinger 		mutex_unlock(&data->lock);
15278f83902SAndreas Klinger 		return -EIO;
15378f83902SAndreas Klinger 	}
15478f83902SAndreas Klinger 
15578f83902SAndreas Klinger 	ret = i2c_smbus_read_word_swapped(data->client,
15678f83902SAndreas Klinger 						SRF08_READ_ECHO_1_HIGH);
15778f83902SAndreas Klinger 	if (ret < 0) {
15878f83902SAndreas Klinger 		dev_err(&client->dev, "cannot read distance: ret=%d\n", ret);
15978f83902SAndreas Klinger 		mutex_unlock(&data->lock);
16078f83902SAndreas Klinger 		return ret;
16178f83902SAndreas Klinger 	}
16278f83902SAndreas Klinger 
16378f83902SAndreas Klinger 	mutex_unlock(&data->lock);
16478f83902SAndreas Klinger 
16578f83902SAndreas Klinger 	return ret;
16678f83902SAndreas Klinger }
16778f83902SAndreas Klinger 
168a8319593SAndreas Klinger static irqreturn_t srf08_trigger_handler(int irq, void *p)
169a8319593SAndreas Klinger {
170a8319593SAndreas Klinger 	struct iio_poll_func *pf = p;
171a8319593SAndreas Klinger 	struct iio_dev *indio_dev = pf->indio_dev;
172a8319593SAndreas Klinger 	struct srf08_data *data = iio_priv(indio_dev);
173a8319593SAndreas Klinger 	s16 sensor_data;
174a8319593SAndreas Klinger 
175a8319593SAndreas Klinger 	sensor_data = srf08_read_ranging(data);
176a8319593SAndreas Klinger 	if (sensor_data < 0)
177a8319593SAndreas Klinger 		goto err;
178a8319593SAndreas Klinger 
179a8319593SAndreas Klinger 	mutex_lock(&data->lock);
180a8319593SAndreas Klinger 
181a8319593SAndreas Klinger 	data->buffer[0] = sensor_data;
182a8319593SAndreas Klinger 	iio_push_to_buffers_with_timestamp(indio_dev,
183a8319593SAndreas Klinger 						data->buffer, pf->timestamp);
184a8319593SAndreas Klinger 
185a8319593SAndreas Klinger 	mutex_unlock(&data->lock);
186a8319593SAndreas Klinger err:
187a8319593SAndreas Klinger 	iio_trigger_notify_done(indio_dev->trig);
188a8319593SAndreas Klinger 	return IRQ_HANDLED;
189a8319593SAndreas Klinger }
190a8319593SAndreas Klinger 
19178f83902SAndreas Klinger static int srf08_read_raw(struct iio_dev *indio_dev,
19278f83902SAndreas Klinger 			    struct iio_chan_spec const *channel, int *val,
19378f83902SAndreas Klinger 			    int *val2, long mask)
19478f83902SAndreas Klinger {
19578f83902SAndreas Klinger 	struct srf08_data *data = iio_priv(indio_dev);
19678f83902SAndreas Klinger 	int ret;
19778f83902SAndreas Klinger 
19878f83902SAndreas Klinger 	if (channel->type != IIO_DISTANCE)
19978f83902SAndreas Klinger 		return -EINVAL;
20078f83902SAndreas Klinger 
20178f83902SAndreas Klinger 	switch (mask) {
20278f83902SAndreas Klinger 	case IIO_CHAN_INFO_RAW:
20378f83902SAndreas Klinger 		ret = srf08_read_ranging(data);
20478f83902SAndreas Klinger 		if (ret < 0)
20578f83902SAndreas Klinger 			return ret;
20678f83902SAndreas Klinger 		*val = ret;
20778f83902SAndreas Klinger 		return IIO_VAL_INT;
20878f83902SAndreas Klinger 	case IIO_CHAN_INFO_SCALE:
20978f83902SAndreas Klinger 		/* 1 LSB is 1 cm */
21078f83902SAndreas Klinger 		*val = 0;
21178f83902SAndreas Klinger 		*val2 = 10000;
21278f83902SAndreas Klinger 		return IIO_VAL_INT_PLUS_MICRO;
21378f83902SAndreas Klinger 	default:
21478f83902SAndreas Klinger 		return -EINVAL;
21578f83902SAndreas Klinger 	}
21678f83902SAndreas Klinger }
21778f83902SAndreas Klinger 
21878f83902SAndreas Klinger static ssize_t srf08_show_range_mm_available(struct device *dev,
21978f83902SAndreas Klinger 				struct device_attribute *attr, char *buf)
22078f83902SAndreas Klinger {
22178f83902SAndreas Klinger 	return sprintf(buf, "[0.043 0.043 11.008]\n");
22278f83902SAndreas Klinger }
22378f83902SAndreas Klinger 
22478f83902SAndreas Klinger static IIO_DEVICE_ATTR(sensor_max_range_available, S_IRUGO,
22578f83902SAndreas Klinger 				srf08_show_range_mm_available, NULL, 0);
22678f83902SAndreas Klinger 
22778f83902SAndreas Klinger static ssize_t srf08_show_range_mm(struct device *dev,
22878f83902SAndreas Klinger 				struct device_attribute *attr, char *buf)
22978f83902SAndreas Klinger {
23078f83902SAndreas Klinger 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
23178f83902SAndreas Klinger 	struct srf08_data *data = iio_priv(indio_dev);
23278f83902SAndreas Klinger 
23378f83902SAndreas Klinger 	return sprintf(buf, "%d.%03d\n", data->range_mm / 1000,
23478f83902SAndreas Klinger 						data->range_mm % 1000);
23578f83902SAndreas Klinger }
23678f83902SAndreas Klinger 
23778f83902SAndreas Klinger /*
23878f83902SAndreas Klinger  * set the range of the sensor to an even multiple of 43 mm
23978f83902SAndreas Klinger  * which corresponds to 1 LSB in the register
24078f83902SAndreas Klinger  *
24178f83902SAndreas Klinger  * register value    corresponding range
24278f83902SAndreas Klinger  *         0x00             43 mm
24378f83902SAndreas Klinger  *         0x01             86 mm
24478f83902SAndreas Klinger  *         0x02            129 mm
24578f83902SAndreas Klinger  *         ...
24678f83902SAndreas Klinger  *         0xFF          11008 mm
24778f83902SAndreas Klinger  */
24878f83902SAndreas Klinger static ssize_t srf08_write_range_mm(struct srf08_data *data, unsigned int val)
24978f83902SAndreas Klinger {
25078f83902SAndreas Klinger 	int ret;
25178f83902SAndreas Klinger 	struct i2c_client *client = data->client;
25278f83902SAndreas Klinger 	unsigned int mod;
25378f83902SAndreas Klinger 	u8 regval;
25478f83902SAndreas Klinger 
25578f83902SAndreas Klinger 	ret = val / 43 - 1;
25678f83902SAndreas Klinger 	mod = val % 43;
25778f83902SAndreas Klinger 
25878f83902SAndreas Klinger 	if (mod || (ret < 0) || (ret > 255))
25978f83902SAndreas Klinger 		return -EINVAL;
26078f83902SAndreas Klinger 
26178f83902SAndreas Klinger 	regval = ret;
26278f83902SAndreas Klinger 
26378f83902SAndreas Klinger 	mutex_lock(&data->lock);
26478f83902SAndreas Klinger 
26578f83902SAndreas Klinger 	ret = i2c_smbus_write_byte_data(client, SRF08_WRITE_RANGE, regval);
26678f83902SAndreas Klinger 	if (ret < 0) {
26778f83902SAndreas Klinger 		dev_err(&client->dev, "write_range - err: %d\n", ret);
26878f83902SAndreas Klinger 		mutex_unlock(&data->lock);
26978f83902SAndreas Klinger 		return ret;
27078f83902SAndreas Klinger 	}
27178f83902SAndreas Klinger 
27278f83902SAndreas Klinger 	data->range_mm = val;
27378f83902SAndreas Klinger 
27478f83902SAndreas Klinger 	mutex_unlock(&data->lock);
27578f83902SAndreas Klinger 
27678f83902SAndreas Klinger 	return 0;
27778f83902SAndreas Klinger }
27878f83902SAndreas Klinger 
27978f83902SAndreas Klinger static ssize_t srf08_store_range_mm(struct device *dev,
28078f83902SAndreas Klinger 					struct device_attribute *attr,
28178f83902SAndreas Klinger 					const char *buf, size_t len)
28278f83902SAndreas Klinger {
28378f83902SAndreas Klinger 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
28478f83902SAndreas Klinger 	struct srf08_data *data = iio_priv(indio_dev);
28578f83902SAndreas Klinger 	int ret;
28678f83902SAndreas Klinger 	int integer, fract;
28778f83902SAndreas Klinger 
28878f83902SAndreas Klinger 	ret = iio_str_to_fixpoint(buf, 100, &integer, &fract);
28978f83902SAndreas Klinger 	if (ret)
29078f83902SAndreas Klinger 		return ret;
29178f83902SAndreas Klinger 
29278f83902SAndreas Klinger 	ret = srf08_write_range_mm(data, integer * 1000 + fract);
29378f83902SAndreas Klinger 	if (ret < 0)
29478f83902SAndreas Klinger 		return ret;
29578f83902SAndreas Klinger 
29678f83902SAndreas Klinger 	return len;
29778f83902SAndreas Klinger }
29878f83902SAndreas Klinger 
29978f83902SAndreas Klinger static IIO_DEVICE_ATTR(sensor_max_range, S_IRUGO | S_IWUSR,
30078f83902SAndreas Klinger 			srf08_show_range_mm, srf08_store_range_mm, 0);
30178f83902SAndreas Klinger 
30278f83902SAndreas Klinger static ssize_t srf08_show_sensitivity_available(struct device *dev,
30378f83902SAndreas Klinger 				struct device_attribute *attr, char *buf)
30478f83902SAndreas Klinger {
30578f83902SAndreas Klinger 	int i, len = 0;
306c5bf4a04SAndreas Klinger 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
307c5bf4a04SAndreas Klinger 	struct srf08_data *data = iio_priv(indio_dev);
30878f83902SAndreas Klinger 
309c5bf4a04SAndreas Klinger 	for (i = 0; i < data->chip_info->num_sensitivity_avail; i++)
310c5bf4a04SAndreas Klinger 		if (data->chip_info->sensitivity_avail[i])
311c5bf4a04SAndreas Klinger 			len += sprintf(buf + len, "%d ",
312c5bf4a04SAndreas Klinger 				data->chip_info->sensitivity_avail[i]);
31378f83902SAndreas Klinger 
31478f83902SAndreas Klinger 	len += sprintf(buf + len, "\n");
31578f83902SAndreas Klinger 
31678f83902SAndreas Klinger 	return len;
31778f83902SAndreas Klinger }
31878f83902SAndreas Klinger 
31978f83902SAndreas Klinger static IIO_DEVICE_ATTR(sensor_sensitivity_available, S_IRUGO,
32078f83902SAndreas Klinger 				srf08_show_sensitivity_available, NULL, 0);
32178f83902SAndreas Klinger 
32278f83902SAndreas Klinger static ssize_t srf08_show_sensitivity(struct device *dev,
32378f83902SAndreas Klinger 				struct device_attribute *attr, char *buf)
32478f83902SAndreas Klinger {
32578f83902SAndreas Klinger 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
32678f83902SAndreas Klinger 	struct srf08_data *data = iio_priv(indio_dev);
32778f83902SAndreas Klinger 	int len;
32878f83902SAndreas Klinger 
32978f83902SAndreas Klinger 	len = sprintf(buf, "%d\n", data->sensitivity);
33078f83902SAndreas Klinger 
33178f83902SAndreas Klinger 	return len;
33278f83902SAndreas Klinger }
33378f83902SAndreas Klinger 
33478f83902SAndreas Klinger static ssize_t srf08_write_sensitivity(struct srf08_data *data,
33578f83902SAndreas Klinger 							unsigned int val)
33678f83902SAndreas Klinger {
33778f83902SAndreas Klinger 	struct i2c_client *client = data->client;
33878f83902SAndreas Klinger 	int ret, i;
33978f83902SAndreas Klinger 	u8 regval;
34078f83902SAndreas Klinger 
341c5bf4a04SAndreas Klinger 	if (!val)
342c5bf4a04SAndreas Klinger 		return -EINVAL;
343c5bf4a04SAndreas Klinger 
344c5bf4a04SAndreas Klinger 	for (i = 0; i < data->chip_info->num_sensitivity_avail; i++)
345c5bf4a04SAndreas Klinger 		if (val && (val == data->chip_info->sensitivity_avail[i])) {
34678f83902SAndreas Klinger 			regval = i;
34778f83902SAndreas Klinger 			break;
34878f83902SAndreas Klinger 		}
34978f83902SAndreas Klinger 
350c5bf4a04SAndreas Klinger 	if (i >= data->chip_info->num_sensitivity_avail)
35178f83902SAndreas Klinger 		return -EINVAL;
35278f83902SAndreas Klinger 
35378f83902SAndreas Klinger 	mutex_lock(&data->lock);
35478f83902SAndreas Klinger 
355c5bf4a04SAndreas Klinger 	ret = i2c_smbus_write_byte_data(client, SRF08_WRITE_MAX_GAIN, regval);
35678f83902SAndreas Klinger 	if (ret < 0) {
35778f83902SAndreas Klinger 		dev_err(&client->dev, "write_sensitivity - err: %d\n", ret);
35878f83902SAndreas Klinger 		mutex_unlock(&data->lock);
35978f83902SAndreas Klinger 		return ret;
36078f83902SAndreas Klinger 	}
36178f83902SAndreas Klinger 
36278f83902SAndreas Klinger 	data->sensitivity = val;
36378f83902SAndreas Klinger 
36478f83902SAndreas Klinger 	mutex_unlock(&data->lock);
36578f83902SAndreas Klinger 
36678f83902SAndreas Klinger 	return 0;
36778f83902SAndreas Klinger }
36878f83902SAndreas Klinger 
36978f83902SAndreas Klinger static ssize_t srf08_store_sensitivity(struct device *dev,
37078f83902SAndreas Klinger 						struct device_attribute *attr,
37178f83902SAndreas Klinger 						const char *buf, size_t len)
37278f83902SAndreas Klinger {
37378f83902SAndreas Klinger 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
37478f83902SAndreas Klinger 	struct srf08_data *data = iio_priv(indio_dev);
37578f83902SAndreas Klinger 	int ret;
37678f83902SAndreas Klinger 	unsigned int val;
37778f83902SAndreas Klinger 
37878f83902SAndreas Klinger 	ret = kstrtouint(buf, 10, &val);
37978f83902SAndreas Klinger 	if (ret)
38078f83902SAndreas Klinger 		return ret;
38178f83902SAndreas Klinger 
38278f83902SAndreas Klinger 	ret = srf08_write_sensitivity(data, val);
38378f83902SAndreas Klinger 	if (ret < 0)
38478f83902SAndreas Klinger 		return ret;
38578f83902SAndreas Klinger 
38678f83902SAndreas Klinger 	return len;
38778f83902SAndreas Klinger }
38878f83902SAndreas Klinger 
38978f83902SAndreas Klinger static IIO_DEVICE_ATTR(sensor_sensitivity, S_IRUGO | S_IWUSR,
39078f83902SAndreas Klinger 			srf08_show_sensitivity, srf08_store_sensitivity, 0);
39178f83902SAndreas Klinger 
39278f83902SAndreas Klinger static struct attribute *srf08_attributes[] = {
39378f83902SAndreas Klinger 	&iio_dev_attr_sensor_max_range.dev_attr.attr,
39478f83902SAndreas Klinger 	&iio_dev_attr_sensor_max_range_available.dev_attr.attr,
39578f83902SAndreas Klinger 	&iio_dev_attr_sensor_sensitivity.dev_attr.attr,
39678f83902SAndreas Klinger 	&iio_dev_attr_sensor_sensitivity_available.dev_attr.attr,
39778f83902SAndreas Klinger 	NULL,
39878f83902SAndreas Klinger };
39978f83902SAndreas Klinger 
40078f83902SAndreas Klinger static const struct attribute_group srf08_attribute_group = {
40178f83902SAndreas Klinger 	.attrs = srf08_attributes,
40278f83902SAndreas Klinger };
40378f83902SAndreas Klinger 
40478f83902SAndreas Klinger static const struct iio_chan_spec srf08_channels[] = {
40578f83902SAndreas Klinger 	{
40678f83902SAndreas Klinger 		.type = IIO_DISTANCE,
40778f83902SAndreas Klinger 		.info_mask_separate =
40878f83902SAndreas Klinger 				BIT(IIO_CHAN_INFO_RAW) |
40978f83902SAndreas Klinger 				BIT(IIO_CHAN_INFO_SCALE),
410a8319593SAndreas Klinger 		.scan_index = 0,
411a8319593SAndreas Klinger 		.scan_type = {
412a8319593SAndreas Klinger 			.sign = 's',
413a8319593SAndreas Klinger 			.realbits = 16,
414a8319593SAndreas Klinger 			.storagebits = 16,
415a8319593SAndreas Klinger 			.endianness = IIO_CPU,
41678f83902SAndreas Klinger 		},
417a8319593SAndreas Klinger 	},
418a8319593SAndreas Klinger 	IIO_CHAN_SOFT_TIMESTAMP(1),
41978f83902SAndreas Klinger };
42078f83902SAndreas Klinger 
42178f83902SAndreas Klinger static const struct iio_info srf08_info = {
42278f83902SAndreas Klinger 	.read_raw = srf08_read_raw,
42378f83902SAndreas Klinger 	.attrs = &srf08_attribute_group,
42478f83902SAndreas Klinger 	.driver_module = THIS_MODULE,
42578f83902SAndreas Klinger };
42678f83902SAndreas Klinger 
42778f83902SAndreas Klinger static int srf08_probe(struct i2c_client *client,
42878f83902SAndreas Klinger 					 const struct i2c_device_id *id)
42978f83902SAndreas Klinger {
43078f83902SAndreas Klinger 	struct iio_dev *indio_dev;
43178f83902SAndreas Klinger 	struct srf08_data *data;
43278f83902SAndreas Klinger 	int ret;
43378f83902SAndreas Klinger 
43478f83902SAndreas Klinger 	if (!i2c_check_functionality(client->adapter,
43578f83902SAndreas Klinger 					I2C_FUNC_SMBUS_READ_BYTE_DATA |
43678f83902SAndreas Klinger 					I2C_FUNC_SMBUS_WRITE_BYTE_DATA |
43778f83902SAndreas Klinger 					I2C_FUNC_SMBUS_READ_WORD_DATA))
43878f83902SAndreas Klinger 		return -ENODEV;
43978f83902SAndreas Klinger 
44078f83902SAndreas Klinger 	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
44178f83902SAndreas Klinger 	if (!indio_dev)
44278f83902SAndreas Klinger 		return -ENOMEM;
44378f83902SAndreas Klinger 
44478f83902SAndreas Klinger 	data = iio_priv(indio_dev);
44578f83902SAndreas Klinger 	i2c_set_clientdata(client, indio_dev);
44678f83902SAndreas Klinger 	data->client = client;
447c5bf4a04SAndreas Klinger 	data->sensor_type = (enum srf08_sensor_type)id->driver_data;
44878f83902SAndreas Klinger 
449c5bf4a04SAndreas Klinger 	switch (data->sensor_type) {
450c5bf4a04SAndreas Klinger 	case SRF08:
451c5bf4a04SAndreas Klinger 		data->chip_info = &srf08_chip_info;
452c5bf4a04SAndreas Klinger 		break;
453c5bf4a04SAndreas Klinger 	case SRF10:
454c5bf4a04SAndreas Klinger 		data->chip_info = &srf10_chip_info;
455c5bf4a04SAndreas Klinger 		break;
456c5bf4a04SAndreas Klinger 	default:
457c5bf4a04SAndreas Klinger 		return -EINVAL;
458c5bf4a04SAndreas Klinger 	}
459c5bf4a04SAndreas Klinger 
460c5bf4a04SAndreas Klinger 	indio_dev->name = id->name;
46178f83902SAndreas Klinger 	indio_dev->dev.parent = &client->dev;
46278f83902SAndreas Klinger 	indio_dev->modes = INDIO_DIRECT_MODE;
46378f83902SAndreas Klinger 	indio_dev->info = &srf08_info;
46478f83902SAndreas Klinger 	indio_dev->channels = srf08_channels;
46578f83902SAndreas Klinger 	indio_dev->num_channels = ARRAY_SIZE(srf08_channels);
46678f83902SAndreas Klinger 
46778f83902SAndreas Klinger 	mutex_init(&data->lock);
46878f83902SAndreas Klinger 
469a8319593SAndreas Klinger 	ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev,
470a8319593SAndreas Klinger 			iio_pollfunc_store_time, srf08_trigger_handler, NULL);
471a8319593SAndreas Klinger 	if (ret < 0) {
472a8319593SAndreas Klinger 		dev_err(&client->dev, "setup of iio triggered buffer failed\n");
473a8319593SAndreas Klinger 		return ret;
474a8319593SAndreas Klinger 	}
475a8319593SAndreas Klinger 
47678f83902SAndreas Klinger 	/*
47778f83902SAndreas Klinger 	 * set default values of device here
47878f83902SAndreas Klinger 	 * these register values cannot be read from the hardware
47978f83902SAndreas Klinger 	 * therefore set driver specific default values
48078f83902SAndreas Klinger 	 */
48178f83902SAndreas Klinger 	ret = srf08_write_range_mm(data, SRF08_DEFAULT_RANGE);
48278f83902SAndreas Klinger 	if (ret < 0)
48378f83902SAndreas Klinger 		return ret;
48478f83902SAndreas Klinger 
485c5bf4a04SAndreas Klinger 	ret = srf08_write_sensitivity(data,
486c5bf4a04SAndreas Klinger 				data->chip_info->sensitivity_default);
48778f83902SAndreas Klinger 	if (ret < 0)
48878f83902SAndreas Klinger 		return ret;
48978f83902SAndreas Klinger 
49078f83902SAndreas Klinger 	return devm_iio_device_register(&client->dev, indio_dev);
49178f83902SAndreas Klinger }
49278f83902SAndreas Klinger 
493c02b3a11SAndreas Klinger static const struct of_device_id of_srf08_match[] = {
494c5bf4a04SAndreas Klinger 	{ .compatible = "devantech,srf08", (void *)SRF08},
495c5bf4a04SAndreas Klinger 	{ .compatible = "devantech,srf10", (void *)SRF10},
496c02b3a11SAndreas Klinger 	{},
497c02b3a11SAndreas Klinger };
498c02b3a11SAndreas Klinger 
499c02b3a11SAndreas Klinger MODULE_DEVICE_TABLE(of, of_srf08_match);
500c02b3a11SAndreas Klinger 
50178f83902SAndreas Klinger static const struct i2c_device_id srf08_id[] = {
502c5bf4a04SAndreas Klinger 	{ "srf08", SRF08 },
503c5bf4a04SAndreas Klinger 	{ "srf10", SRF10 },
50478f83902SAndreas Klinger 	{ }
50578f83902SAndreas Klinger };
50678f83902SAndreas Klinger MODULE_DEVICE_TABLE(i2c, srf08_id);
50778f83902SAndreas Klinger 
50878f83902SAndreas Klinger static struct i2c_driver srf08_driver = {
50978f83902SAndreas Klinger 	.driver = {
51078f83902SAndreas Klinger 		.name	= "srf08",
511c02b3a11SAndreas Klinger 		.of_match_table	= of_srf08_match,
51278f83902SAndreas Klinger 	},
51378f83902SAndreas Klinger 	.probe = srf08_probe,
51478f83902SAndreas Klinger 	.id_table = srf08_id,
51578f83902SAndreas Klinger };
51678f83902SAndreas Klinger module_i2c_driver(srf08_driver);
51778f83902SAndreas Klinger 
51878f83902SAndreas Klinger MODULE_AUTHOR("Andreas Klinger <ak@it-klinger.de>");
519a8319593SAndreas Klinger MODULE_DESCRIPTION("Devantech SRF08/SRF10 ultrasonic ranger driver");
52078f83902SAndreas Klinger MODULE_LICENSE("GPL");
521