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