Linux 6.7-rc7
[linux-modified.git] / drivers / iio / proximity / srf04.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * SRF04: ultrasonic sensor for distance measuring by using GPIOs
4  *
5  * Copyright (c) 2017 Andreas Klinger <ak@it-klinger.de>
6  *
7  * For details about the device see:
8  * https://www.robot-electronics.co.uk/htm/srf04tech.htm
9  *
10  * the measurement cycle as timing diagram looks like:
11  *
12  *          +---+
13  * GPIO     |   |
14  * trig:  --+   +------------------------------------------------------
15  *          ^   ^
16  *          |<->|
17  *         udelay(trigger_pulse_us)
18  *
19  * ultra           +-+ +-+ +-+
20  * sonic           | | | | | |
21  * burst: ---------+ +-+ +-+ +-----------------------------------------
22  *                           .
23  * ultra                     .              +-+ +-+ +-+
24  * sonic                     .              | | | | | |
25  * echo:  ----------------------------------+ +-+ +-+ +----------------
26  *                           .                        .
27  *                           +------------------------+
28  * GPIO                      |                        |
29  * echo:  -------------------+                        +---------------
30  *                           ^                        ^
31  *                           interrupt                interrupt
32  *                           (ts_rising)              (ts_falling)
33  *                           |<---------------------->|
34  *                              pulse time measured
35  *                              --> one round trip of ultra sonic waves
36  */
37 #include <linux/err.h>
38 #include <linux/gpio/consumer.h>
39 #include <linux/kernel.h>
40 #include <linux/mod_devicetable.h>
41 #include <linux/module.h>
42 #include <linux/platform_device.h>
43 #include <linux/property.h>
44 #include <linux/sched.h>
45 #include <linux/interrupt.h>
46 #include <linux/delay.h>
47 #include <linux/pm_runtime.h>
48 #include <linux/iio/iio.h>
49 #include <linux/iio/sysfs.h>
50
51 struct srf04_cfg {
52         unsigned long trigger_pulse_us;
53 };
54
55 struct srf04_data {
56         struct device           *dev;
57         struct gpio_desc        *gpiod_trig;
58         struct gpio_desc        *gpiod_echo;
59         struct gpio_desc        *gpiod_power;
60         struct mutex            lock;
61         int                     irqnr;
62         ktime_t                 ts_rising;
63         ktime_t                 ts_falling;
64         struct completion       rising;
65         struct completion       falling;
66         const struct srf04_cfg  *cfg;
67         int                     startup_time_ms;
68 };
69
70 static const struct srf04_cfg srf04_cfg = {
71         .trigger_pulse_us = 10,
72 };
73
74 static const struct srf04_cfg mb_lv_cfg = {
75         .trigger_pulse_us = 20,
76 };
77
78 static irqreturn_t srf04_handle_irq(int irq, void *dev_id)
79 {
80         struct iio_dev *indio_dev = dev_id;
81         struct srf04_data *data = iio_priv(indio_dev);
82         ktime_t now = ktime_get();
83
84         if (gpiod_get_value(data->gpiod_echo)) {
85                 data->ts_rising = now;
86                 complete(&data->rising);
87         } else {
88                 data->ts_falling = now;
89                 complete(&data->falling);
90         }
91
92         return IRQ_HANDLED;
93 }
94
95 static int srf04_read(struct srf04_data *data)
96 {
97         int ret;
98         ktime_t ktime_dt;
99         u64 dt_ns;
100         u32 time_ns, distance_mm;
101
102         if (data->gpiod_power) {
103                 ret = pm_runtime_resume_and_get(data->dev);
104                 if (ret < 0)
105                         return ret;
106         }
107         /*
108          * just one read-echo-cycle can take place at a time
109          * ==> lock against concurrent reading calls
110          */
111         mutex_lock(&data->lock);
112
113         reinit_completion(&data->rising);
114         reinit_completion(&data->falling);
115
116         gpiod_set_value(data->gpiod_trig, 1);
117         udelay(data->cfg->trigger_pulse_us);
118         gpiod_set_value(data->gpiod_trig, 0);
119
120         if (data->gpiod_power) {
121                 pm_runtime_mark_last_busy(data->dev);
122                 pm_runtime_put_autosuspend(data->dev);
123         }
124
125         /* it should not take more than 20 ms until echo is rising */
126         ret = wait_for_completion_killable_timeout(&data->rising, HZ/50);
127         if (ret < 0) {
128                 mutex_unlock(&data->lock);
129                 return ret;
130         } else if (ret == 0) {
131                 mutex_unlock(&data->lock);
132                 return -ETIMEDOUT;
133         }
134
135         /* it cannot take more than 50 ms until echo is falling */
136         ret = wait_for_completion_killable_timeout(&data->falling, HZ/20);
137         if (ret < 0) {
138                 mutex_unlock(&data->lock);
139                 return ret;
140         } else if (ret == 0) {
141                 mutex_unlock(&data->lock);
142                 return -ETIMEDOUT;
143         }
144
145         ktime_dt = ktime_sub(data->ts_falling, data->ts_rising);
146
147         mutex_unlock(&data->lock);
148
149         dt_ns = ktime_to_ns(ktime_dt);
150         /*
151          * measuring more than 6,45 meters is beyond the capabilities of
152          * the supported sensors
153          * ==> filter out invalid results for not measuring echos of
154          *     another us sensor
155          *
156          * formula:
157          *         distance     6,45 * 2 m
158          * time = ---------- = ------------ = 40438871 ns
159          *          speed         319 m/s
160          *
161          * using a minimum speed at -20 °C of 319 m/s
162          */
163         if (dt_ns > 40438871)
164                 return -EIO;
165
166         time_ns = dt_ns;
167
168         /*
169          * the speed as function of the temperature is approximately:
170          *
171          * speed = 331,5 + 0,6 * Temp
172          *   with Temp in °C
173          *   and speed in m/s
174          *
175          * use 343,5 m/s as ultrasonic speed at 20 °C here in absence of the
176          * temperature
177          *
178          * therefore:
179          *             time     343,5     time * 106
180          * distance = ------ * ------- = ------------
181          *             10^6         2         617176
182          *   with time in ns
183          *   and distance in mm (one way)
184          *
185          * because we limit to 6,45 meters the multiplication with 106 just
186          * fits into 32 bit
187          */
188         distance_mm = time_ns * 106 / 617176;
189
190         return distance_mm;
191 }
192
193 static int srf04_read_raw(struct iio_dev *indio_dev,
194                             struct iio_chan_spec const *channel, int *val,
195                             int *val2, long info)
196 {
197         struct srf04_data *data = iio_priv(indio_dev);
198         int ret;
199
200         if (channel->type != IIO_DISTANCE)
201                 return -EINVAL;
202
203         switch (info) {
204         case IIO_CHAN_INFO_RAW:
205                 ret = srf04_read(data);
206                 if (ret < 0)
207                         return ret;
208                 *val = ret;
209                 return IIO_VAL_INT;
210         case IIO_CHAN_INFO_SCALE:
211                 /*
212                  * theoretical maximum resolution is 3 mm
213                  * 1 LSB is 1 mm
214                  */
215                 *val = 0;
216                 *val2 = 1000;
217                 return IIO_VAL_INT_PLUS_MICRO;
218         default:
219                 return -EINVAL;
220         }
221 }
222
223 static const struct iio_info srf04_iio_info = {
224         .read_raw               = srf04_read_raw,
225 };
226
227 static const struct iio_chan_spec srf04_chan_spec[] = {
228         {
229                 .type = IIO_DISTANCE,
230                 .info_mask_separate =
231                                 BIT(IIO_CHAN_INFO_RAW) |
232                                 BIT(IIO_CHAN_INFO_SCALE),
233         },
234 };
235
236 static const struct of_device_id of_srf04_match[] = {
237         { .compatible = "devantech,srf04", .data = &srf04_cfg },
238         { .compatible = "maxbotix,mb1000", .data = &mb_lv_cfg },
239         { .compatible = "maxbotix,mb1010", .data = &mb_lv_cfg },
240         { .compatible = "maxbotix,mb1020", .data = &mb_lv_cfg },
241         { .compatible = "maxbotix,mb1030", .data = &mb_lv_cfg },
242         { .compatible = "maxbotix,mb1040", .data = &mb_lv_cfg },
243         {},
244 };
245
246 MODULE_DEVICE_TABLE(of, of_srf04_match);
247
248 static int srf04_probe(struct platform_device *pdev)
249 {
250         struct device *dev = &pdev->dev;
251         struct srf04_data *data;
252         struct iio_dev *indio_dev;
253         int ret;
254
255         indio_dev = devm_iio_device_alloc(dev, sizeof(struct srf04_data));
256         if (!indio_dev) {
257                 dev_err(dev, "failed to allocate IIO device\n");
258                 return -ENOMEM;
259         }
260
261         data = iio_priv(indio_dev);
262         data->dev = dev;
263         data->cfg = device_get_match_data(dev);
264
265         mutex_init(&data->lock);
266         init_completion(&data->rising);
267         init_completion(&data->falling);
268
269         data->gpiod_trig = devm_gpiod_get(dev, "trig", GPIOD_OUT_LOW);
270         if (IS_ERR(data->gpiod_trig)) {
271                 dev_err(dev, "failed to get trig-gpios: err=%ld\n",
272                                         PTR_ERR(data->gpiod_trig));
273                 return PTR_ERR(data->gpiod_trig);
274         }
275
276         data->gpiod_echo = devm_gpiod_get(dev, "echo", GPIOD_IN);
277         if (IS_ERR(data->gpiod_echo)) {
278                 dev_err(dev, "failed to get echo-gpios: err=%ld\n",
279                                         PTR_ERR(data->gpiod_echo));
280                 return PTR_ERR(data->gpiod_echo);
281         }
282
283         data->gpiod_power = devm_gpiod_get_optional(dev, "power",
284                                                                 GPIOD_OUT_LOW);
285         if (IS_ERR(data->gpiod_power)) {
286                 dev_err(dev, "failed to get power-gpios: err=%ld\n",
287                                                 PTR_ERR(data->gpiod_power));
288                 return PTR_ERR(data->gpiod_power);
289         }
290         if (data->gpiod_power) {
291                 data->startup_time_ms = 100;
292                 device_property_read_u32(dev, "startup-time-ms", &data->startup_time_ms);
293                 dev_dbg(dev, "using power gpio: startup-time-ms=%d\n",
294                                                         data->startup_time_ms);
295         }
296
297         if (gpiod_cansleep(data->gpiod_echo)) {
298                 dev_err(data->dev, "cansleep-GPIOs not supported\n");
299                 return -ENODEV;
300         }
301
302         data->irqnr = gpiod_to_irq(data->gpiod_echo);
303         if (data->irqnr < 0) {
304                 dev_err(data->dev, "gpiod_to_irq: %d\n", data->irqnr);
305                 return data->irqnr;
306         }
307
308         ret = devm_request_irq(dev, data->irqnr, srf04_handle_irq,
309                         IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
310                         pdev->name, indio_dev);
311         if (ret < 0) {
312                 dev_err(data->dev, "request_irq: %d\n", ret);
313                 return ret;
314         }
315
316         platform_set_drvdata(pdev, indio_dev);
317
318         indio_dev->name = "srf04";
319         indio_dev->info = &srf04_iio_info;
320         indio_dev->modes = INDIO_DIRECT_MODE;
321         indio_dev->channels = srf04_chan_spec;
322         indio_dev->num_channels = ARRAY_SIZE(srf04_chan_spec);
323
324         ret = iio_device_register(indio_dev);
325         if (ret < 0) {
326                 dev_err(data->dev, "iio_device_register: %d\n", ret);
327                 return ret;
328         }
329
330         if (data->gpiod_power) {
331                 pm_runtime_set_autosuspend_delay(data->dev, 1000);
332                 pm_runtime_use_autosuspend(data->dev);
333
334                 ret = pm_runtime_set_active(data->dev);
335                 if (ret) {
336                         dev_err(data->dev, "pm_runtime_set_active: %d\n", ret);
337                         iio_device_unregister(indio_dev);
338                 }
339
340                 pm_runtime_enable(data->dev);
341                 pm_runtime_idle(data->dev);
342         }
343
344         return ret;
345 }
346
347 static void srf04_remove(struct platform_device *pdev)
348 {
349         struct iio_dev *indio_dev = platform_get_drvdata(pdev);
350         struct srf04_data *data = iio_priv(indio_dev);
351
352         iio_device_unregister(indio_dev);
353
354         if (data->gpiod_power) {
355                 pm_runtime_disable(data->dev);
356                 pm_runtime_set_suspended(data->dev);
357         }
358 }
359
360 static int  srf04_pm_runtime_suspend(struct device *dev)
361 {
362         struct platform_device *pdev = container_of(dev,
363                                                 struct platform_device, dev);
364         struct iio_dev *indio_dev = platform_get_drvdata(pdev);
365         struct srf04_data *data = iio_priv(indio_dev);
366
367         gpiod_set_value(data->gpiod_power, 0);
368
369         return 0;
370 }
371
372 static int srf04_pm_runtime_resume(struct device *dev)
373 {
374         struct platform_device *pdev = container_of(dev,
375                                                 struct platform_device, dev);
376         struct iio_dev *indio_dev = platform_get_drvdata(pdev);
377         struct srf04_data *data = iio_priv(indio_dev);
378
379         gpiod_set_value(data->gpiod_power, 1);
380         msleep(data->startup_time_ms);
381
382         return 0;
383 }
384
385 static const struct dev_pm_ops srf04_pm_ops = {
386         RUNTIME_PM_OPS(srf04_pm_runtime_suspend,
387                        srf04_pm_runtime_resume, NULL)
388 };
389
390 static struct platform_driver srf04_driver = {
391         .probe          = srf04_probe,
392         .remove_new     = srf04_remove,
393         .driver         = {
394                 .name           = "srf04-gpio",
395                 .of_match_table = of_srf04_match,
396                 .pm             = pm_ptr(&srf04_pm_ops),
397         },
398 };
399
400 module_platform_driver(srf04_driver);
401
402 MODULE_AUTHOR("Andreas Klinger <ak@it-klinger.de>");
403 MODULE_DESCRIPTION("SRF04 ultrasonic sensor for distance measuring using GPIOs");
404 MODULE_LICENSE("GPL");
405 MODULE_ALIAS("platform:srf04");