1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * SRF04: ultrasonic sensor for distance measuring by using GPIOs
5 * Copyright (c) 2017 Andreas Klinger <ak@it-klinger.de>
7 * For details about the device see:
8 * https://www.robot-electronics.co.uk/htm/srf04tech.htm
10 * the measurement cycle as timing diagram looks like:
14 * trig: --+ +------------------------------------------------------
17 * udelay(trigger_pulse_us)
21 * burst: ---------+ +-+ +-+ +-----------------------------------------
25 * echo: ----------------------------------+ +-+ +-+ +----------------
27 * +------------------------+
29 * echo: -------------------+ +---------------
32 * (ts_rising) (ts_falling)
33 * |<---------------------->|
35 * --> one round trip of ultra sonic waves
37 #include <linux/err.h>
38 #include <linux/gpio/consumer.h>
39 #include <linux/kernel.h>
40 #include <linux/module.h>
42 #include <linux/of_device.h>
43 #include <linux/platform_device.h>
44 #include <linux/property.h>
45 #include <linux/sched.h>
46 #include <linux/interrupt.h>
47 #include <linux/delay.h>
48 #include <linux/pm_runtime.h>
49 #include <linux/iio/iio.h>
50 #include <linux/iio/sysfs.h>
53 unsigned long trigger_pulse_us
;
58 struct gpio_desc
*gpiod_trig
;
59 struct gpio_desc
*gpiod_echo
;
60 struct gpio_desc
*gpiod_power
;
65 struct completion rising
;
66 struct completion falling
;
67 const struct srf04_cfg
*cfg
;
71 static const struct srf04_cfg srf04_cfg
= {
72 .trigger_pulse_us
= 10,
75 static const struct srf04_cfg mb_lv_cfg
= {
76 .trigger_pulse_us
= 20,
79 static irqreturn_t
srf04_handle_irq(int irq
, void *dev_id
)
81 struct iio_dev
*indio_dev
= dev_id
;
82 struct srf04_data
*data
= iio_priv(indio_dev
);
83 ktime_t now
= ktime_get();
85 if (gpiod_get_value(data
->gpiod_echo
)) {
86 data
->ts_rising
= now
;
87 complete(&data
->rising
);
89 data
->ts_falling
= now
;
90 complete(&data
->falling
);
96 static int srf04_read(struct srf04_data
*data
)
101 u32 time_ns
, distance_mm
;
103 if (data
->gpiod_power
)
104 pm_runtime_get_sync(data
->dev
);
107 * just one read-echo-cycle can take place at a time
108 * ==> lock against concurrent reading calls
110 mutex_lock(&data
->lock
);
112 reinit_completion(&data
->rising
);
113 reinit_completion(&data
->falling
);
115 gpiod_set_value(data
->gpiod_trig
, 1);
116 udelay(data
->cfg
->trigger_pulse_us
);
117 gpiod_set_value(data
->gpiod_trig
, 0);
119 if (data
->gpiod_power
) {
120 pm_runtime_mark_last_busy(data
->dev
);
121 pm_runtime_put_autosuspend(data
->dev
);
124 /* it should not take more than 20 ms until echo is rising */
125 ret
= wait_for_completion_killable_timeout(&data
->rising
, HZ
/50);
127 mutex_unlock(&data
->lock
);
129 } else if (ret
== 0) {
130 mutex_unlock(&data
->lock
);
134 /* it cannot take more than 50 ms until echo is falling */
135 ret
= wait_for_completion_killable_timeout(&data
->falling
, HZ
/20);
137 mutex_unlock(&data
->lock
);
139 } else if (ret
== 0) {
140 mutex_unlock(&data
->lock
);
144 ktime_dt
= ktime_sub(data
->ts_falling
, data
->ts_rising
);
146 mutex_unlock(&data
->lock
);
148 dt_ns
= ktime_to_ns(ktime_dt
);
150 * measuring more than 6,45 meters is beyond the capabilities of
151 * the supported sensors
152 * ==> filter out invalid results for not measuring echos of
156 * distance 6,45 * 2 m
157 * time = ---------- = ------------ = 40438871 ns
160 * using a minimum speed at -20 °C of 319 m/s
162 if (dt_ns
> 40438871)
168 * the speed as function of the temperature is approximately:
170 * speed = 331,5 + 0,6 * Temp
174 * use 343,5 m/s as ultrasonic speed at 20 °C here in absence of the
178 * time 343,5 time * 106
179 * distance = ------ * ------- = ------------
182 * and distance in mm (one way)
184 * because we limit to 6,45 meters the multiplication with 106 just
187 distance_mm
= time_ns
* 106 / 617176;
192 static int srf04_read_raw(struct iio_dev
*indio_dev
,
193 struct iio_chan_spec
const *channel
, int *val
,
194 int *val2
, long info
)
196 struct srf04_data
*data
= iio_priv(indio_dev
);
199 if (channel
->type
!= IIO_DISTANCE
)
203 case IIO_CHAN_INFO_RAW
:
204 ret
= srf04_read(data
);
209 case IIO_CHAN_INFO_SCALE
:
211 * theoretical maximum resolution is 3 mm
216 return IIO_VAL_INT_PLUS_MICRO
;
222 static const struct iio_info srf04_iio_info
= {
223 .read_raw
= srf04_read_raw
,
226 static const struct iio_chan_spec srf04_chan_spec
[] = {
228 .type
= IIO_DISTANCE
,
229 .info_mask_separate
=
230 BIT(IIO_CHAN_INFO_RAW
) |
231 BIT(IIO_CHAN_INFO_SCALE
),
235 static const struct of_device_id of_srf04_match
[] = {
236 { .compatible
= "devantech,srf04", .data
= &srf04_cfg
},
237 { .compatible
= "maxbotix,mb1000", .data
= &mb_lv_cfg
},
238 { .compatible
= "maxbotix,mb1010", .data
= &mb_lv_cfg
},
239 { .compatible
= "maxbotix,mb1020", .data
= &mb_lv_cfg
},
240 { .compatible
= "maxbotix,mb1030", .data
= &mb_lv_cfg
},
241 { .compatible
= "maxbotix,mb1040", .data
= &mb_lv_cfg
},
245 MODULE_DEVICE_TABLE(of
, of_srf04_match
);
247 static int srf04_probe(struct platform_device
*pdev
)
249 struct device
*dev
= &pdev
->dev
;
250 struct srf04_data
*data
;
251 struct iio_dev
*indio_dev
;
254 indio_dev
= devm_iio_device_alloc(dev
, sizeof(struct srf04_data
));
256 dev_err(dev
, "failed to allocate IIO device\n");
260 data
= iio_priv(indio_dev
);
262 data
->cfg
= of_match_device(of_srf04_match
, dev
)->data
;
264 mutex_init(&data
->lock
);
265 init_completion(&data
->rising
);
266 init_completion(&data
->falling
);
268 data
->gpiod_trig
= devm_gpiod_get(dev
, "trig", GPIOD_OUT_LOW
);
269 if (IS_ERR(data
->gpiod_trig
)) {
270 dev_err(dev
, "failed to get trig-gpios: err=%ld\n",
271 PTR_ERR(data
->gpiod_trig
));
272 return PTR_ERR(data
->gpiod_trig
);
275 data
->gpiod_echo
= devm_gpiod_get(dev
, "echo", GPIOD_IN
);
276 if (IS_ERR(data
->gpiod_echo
)) {
277 dev_err(dev
, "failed to get echo-gpios: err=%ld\n",
278 PTR_ERR(data
->gpiod_echo
));
279 return PTR_ERR(data
->gpiod_echo
);
282 data
->gpiod_power
= devm_gpiod_get_optional(dev
, "power",
284 if (IS_ERR(data
->gpiod_power
)) {
285 dev_err(dev
, "failed to get power-gpios: err=%ld\n",
286 PTR_ERR(data
->gpiod_power
));
287 return PTR_ERR(data
->gpiod_power
);
289 if (data
->gpiod_power
) {
291 if (of_property_read_u32(dev
->of_node
, "startup-time-ms",
292 &data
->startup_time_ms
))
293 data
->startup_time_ms
= 100;
294 dev_dbg(dev
, "using power gpio: startup-time-ms=%d\n",
295 data
->startup_time_ms
);
298 if (gpiod_cansleep(data
->gpiod_echo
)) {
299 dev_err(data
->dev
, "cansleep-GPIOs not supported\n");
303 data
->irqnr
= gpiod_to_irq(data
->gpiod_echo
);
304 if (data
->irqnr
< 0) {
305 dev_err(data
->dev
, "gpiod_to_irq: %d\n", data
->irqnr
);
309 ret
= devm_request_irq(dev
, data
->irqnr
, srf04_handle_irq
,
310 IRQF_TRIGGER_RISING
| IRQF_TRIGGER_FALLING
,
311 pdev
->name
, indio_dev
);
313 dev_err(data
->dev
, "request_irq: %d\n", ret
);
317 platform_set_drvdata(pdev
, indio_dev
);
319 indio_dev
->name
= "srf04";
320 indio_dev
->info
= &srf04_iio_info
;
321 indio_dev
->modes
= INDIO_DIRECT_MODE
;
322 indio_dev
->channels
= srf04_chan_spec
;
323 indio_dev
->num_channels
= ARRAY_SIZE(srf04_chan_spec
);
325 ret
= iio_device_register(indio_dev
);
327 dev_err(data
->dev
, "iio_device_register: %d\n", ret
);
331 if (data
->gpiod_power
) {
332 pm_runtime_set_autosuspend_delay(data
->dev
, 1000);
333 pm_runtime_use_autosuspend(data
->dev
);
335 ret
= pm_runtime_set_active(data
->dev
);
337 dev_err(data
->dev
, "pm_runtime_set_active: %d\n", ret
);
338 iio_device_unregister(indio_dev
);
341 pm_runtime_enable(data
->dev
);
342 pm_runtime_idle(data
->dev
);
348 static int srf04_remove(struct platform_device
*pdev
)
350 struct iio_dev
*indio_dev
= platform_get_drvdata(pdev
);
351 struct srf04_data
*data
= iio_priv(indio_dev
);
353 iio_device_unregister(indio_dev
);
355 if (data
->gpiod_power
) {
356 pm_runtime_disable(data
->dev
);
357 pm_runtime_set_suspended(data
->dev
);
363 static int __maybe_unused
srf04_pm_runtime_suspend(struct device
*dev
)
365 struct platform_device
*pdev
= container_of(dev
,
366 struct platform_device
, dev
);
367 struct iio_dev
*indio_dev
= platform_get_drvdata(pdev
);
368 struct srf04_data
*data
= iio_priv(indio_dev
);
370 gpiod_set_value(data
->gpiod_power
, 0);
375 static int __maybe_unused
srf04_pm_runtime_resume(struct device
*dev
)
377 struct platform_device
*pdev
= container_of(dev
,
378 struct platform_device
, dev
);
379 struct iio_dev
*indio_dev
= platform_get_drvdata(pdev
);
380 struct srf04_data
*data
= iio_priv(indio_dev
);
382 gpiod_set_value(data
->gpiod_power
, 1);
383 msleep(data
->startup_time_ms
);
388 static const struct dev_pm_ops srf04_pm_ops
= {
389 SET_RUNTIME_PM_OPS(srf04_pm_runtime_suspend
,
390 srf04_pm_runtime_resume
, NULL
)
393 static struct platform_driver srf04_driver
= {
394 .probe
= srf04_probe
,
395 .remove
= srf04_remove
,
397 .name
= "srf04-gpio",
398 .of_match_table
= of_srf04_match
,
403 module_platform_driver(srf04_driver
);
405 MODULE_AUTHOR("Andreas Klinger <ak@it-klinger.de>");
406 MODULE_DESCRIPTION("SRF04 ultrasonic sensor for distance measuring using GPIOs");
407 MODULE_LICENSE("GPL");
408 MODULE_ALIAS("platform:srf04");