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/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>
52 unsigned long trigger_pulse_us
;
57 struct gpio_desc
*gpiod_trig
;
58 struct gpio_desc
*gpiod_echo
;
59 struct gpio_desc
*gpiod_power
;
64 struct completion rising
;
65 struct completion falling
;
66 const struct srf04_cfg
*cfg
;
70 static const struct srf04_cfg srf04_cfg
= {
71 .trigger_pulse_us
= 10,
74 static const struct srf04_cfg mb_lv_cfg
= {
75 .trigger_pulse_us
= 20,
78 static irqreturn_t
srf04_handle_irq(int irq
, void *dev_id
)
80 struct iio_dev
*indio_dev
= dev_id
;
81 struct srf04_data
*data
= iio_priv(indio_dev
);
82 ktime_t now
= ktime_get();
84 if (gpiod_get_value(data
->gpiod_echo
)) {
85 data
->ts_rising
= now
;
86 complete(&data
->rising
);
88 data
->ts_falling
= now
;
89 complete(&data
->falling
);
95 static int srf04_read(struct srf04_data
*data
)
100 u32 time_ns
, distance_mm
;
102 if (data
->gpiod_power
) {
103 ret
= pm_runtime_resume_and_get(data
->dev
);
108 * just one read-echo-cycle can take place at a time
109 * ==> lock against concurrent reading calls
111 mutex_lock(&data
->lock
);
113 reinit_completion(&data
->rising
);
114 reinit_completion(&data
->falling
);
116 gpiod_set_value(data
->gpiod_trig
, 1);
117 udelay(data
->cfg
->trigger_pulse_us
);
118 gpiod_set_value(data
->gpiod_trig
, 0);
120 if (data
->gpiod_power
) {
121 pm_runtime_mark_last_busy(data
->dev
);
122 pm_runtime_put_autosuspend(data
->dev
);
125 /* it should not take more than 20 ms until echo is rising */
126 ret
= wait_for_completion_killable_timeout(&data
->rising
, HZ
/50);
128 mutex_unlock(&data
->lock
);
130 } else if (ret
== 0) {
131 mutex_unlock(&data
->lock
);
135 /* it cannot take more than 50 ms until echo is falling */
136 ret
= wait_for_completion_killable_timeout(&data
->falling
, HZ
/20);
138 mutex_unlock(&data
->lock
);
140 } else if (ret
== 0) {
141 mutex_unlock(&data
->lock
);
145 ktime_dt
= ktime_sub(data
->ts_falling
, data
->ts_rising
);
147 mutex_unlock(&data
->lock
);
149 dt_ns
= ktime_to_ns(ktime_dt
);
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
157 * distance 6,45 * 2 m
158 * time = ---------- = ------------ = 40438871 ns
161 * using a minimum speed at -20 °C of 319 m/s
163 if (dt_ns
> 40438871)
169 * the speed as function of the temperature is approximately:
171 * speed = 331,5 + 0,6 * Temp
175 * use 343,5 m/s as ultrasonic speed at 20 °C here in absence of the
179 * time 343,5 time * 106
180 * distance = ------ * ------- = ------------
183 * and distance in mm (one way)
185 * because we limit to 6,45 meters the multiplication with 106 just
188 distance_mm
= time_ns
* 106 / 617176;
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
)
197 struct srf04_data
*data
= iio_priv(indio_dev
);
200 if (channel
->type
!= IIO_DISTANCE
)
204 case IIO_CHAN_INFO_RAW
:
205 ret
= srf04_read(data
);
210 case IIO_CHAN_INFO_SCALE
:
212 * theoretical maximum resolution is 3 mm
217 return IIO_VAL_INT_PLUS_MICRO
;
223 static const struct iio_info srf04_iio_info
= {
224 .read_raw
= srf04_read_raw
,
227 static const struct iio_chan_spec srf04_chan_spec
[] = {
229 .type
= IIO_DISTANCE
,
230 .info_mask_separate
=
231 BIT(IIO_CHAN_INFO_RAW
) |
232 BIT(IIO_CHAN_INFO_SCALE
),
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
},
246 MODULE_DEVICE_TABLE(of
, of_srf04_match
);
248 static int srf04_probe(struct platform_device
*pdev
)
250 struct device
*dev
= &pdev
->dev
;
251 struct srf04_data
*data
;
252 struct iio_dev
*indio_dev
;
255 indio_dev
= devm_iio_device_alloc(dev
, sizeof(struct srf04_data
));
257 dev_err(dev
, "failed to allocate IIO device\n");
261 data
= iio_priv(indio_dev
);
263 data
->cfg
= device_get_match_data(dev
);
265 mutex_init(&data
->lock
);
266 init_completion(&data
->rising
);
267 init_completion(&data
->falling
);
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
);
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
);
283 data
->gpiod_power
= devm_gpiod_get_optional(dev
, "power",
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
);
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
);
297 if (gpiod_cansleep(data
->gpiod_echo
)) {
298 dev_err(data
->dev
, "cansleep-GPIOs not supported\n");
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
);
308 ret
= devm_request_irq(dev
, data
->irqnr
, srf04_handle_irq
,
309 IRQF_TRIGGER_RISING
| IRQF_TRIGGER_FALLING
,
310 pdev
->name
, indio_dev
);
312 dev_err(data
->dev
, "request_irq: %d\n", ret
);
316 platform_set_drvdata(pdev
, indio_dev
);
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
);
324 ret
= iio_device_register(indio_dev
);
326 dev_err(data
->dev
, "iio_device_register: %d\n", ret
);
330 if (data
->gpiod_power
) {
331 pm_runtime_set_autosuspend_delay(data
->dev
, 1000);
332 pm_runtime_use_autosuspend(data
->dev
);
334 ret
= pm_runtime_set_active(data
->dev
);
336 dev_err(data
->dev
, "pm_runtime_set_active: %d\n", ret
);
337 iio_device_unregister(indio_dev
);
340 pm_runtime_enable(data
->dev
);
341 pm_runtime_idle(data
->dev
);
347 static void srf04_remove(struct platform_device
*pdev
)
349 struct iio_dev
*indio_dev
= platform_get_drvdata(pdev
);
350 struct srf04_data
*data
= iio_priv(indio_dev
);
352 iio_device_unregister(indio_dev
);
354 if (data
->gpiod_power
) {
355 pm_runtime_disable(data
->dev
);
356 pm_runtime_set_suspended(data
->dev
);
360 static int srf04_pm_runtime_suspend(struct device
*dev
)
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
);
367 gpiod_set_value(data
->gpiod_power
, 0);
372 static int srf04_pm_runtime_resume(struct device
*dev
)
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
);
379 gpiod_set_value(data
->gpiod_power
, 1);
380 msleep(data
->startup_time_ms
);
385 static const struct dev_pm_ops srf04_pm_ops
= {
386 RUNTIME_PM_OPS(srf04_pm_runtime_suspend
,
387 srf04_pm_runtime_resume
, NULL
)
390 static struct platform_driver srf04_driver
= {
391 .probe
= srf04_probe
,
392 .remove
= srf04_remove
,
394 .name
= "srf04-gpio",
395 .of_match_table
= of_srf04_match
,
396 .pm
= pm_ptr(&srf04_pm_ops
),
400 module_platform_driver(srf04_driver
);
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");