Lines Matching +full:ping +full:- +full:gpios
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * PING: ultrasonic sensor for distance measuring by using only one GPIOs
5 * Copyright (c) 2019 Andreas Klinger <ak@it-klinger.de>
8 * http://parallax.com/sites/default/files/downloads/28041-LaserPING-2m-Rangefinder-Guide.pdf
9 * http://parallax.com/sites/default/files/downloads/28015-PING-Documentation-v1.6.pdf
14 * ping: __/ \____________/ \________________
16 * |<->| interrupt interrupt
18 * |<---------------------->|
20 * . --> one round trip of ultra sonic waves
47 /* ping sensors */
81 if (gpiod_get_value(data->gpiod_ping)) { in ping_handle_irq()
82 data->ts_rising = now; in ping_handle_irq()
83 complete(&data->rising); in ping_handle_irq()
85 data->ts_falling = now; in ping_handle_irq()
86 complete(&data->falling); in ping_handle_irq()
99 struct platform_device *pdev = to_platform_device(data->dev); in ping_read()
102 * just one read-echo-cycle can take place at a time in ping_read()
105 mutex_lock(&data->lock); in ping_read()
107 reinit_completion(&data->rising); in ping_read()
108 reinit_completion(&data->falling); in ping_read()
110 gpiod_set_value(data->gpiod_ping, 1); in ping_read()
111 udelay(data->cfg->trigger_pulse_us); in ping_read()
112 gpiod_set_value(data->gpiod_ping, 0); in ping_read()
114 ret = gpiod_direction_input(data->gpiod_ping); in ping_read()
116 mutex_unlock(&data->lock); in ping_read()
120 data->irqnr = gpiod_to_irq(data->gpiod_ping); in ping_read()
121 if (data->irqnr < 0) { in ping_read()
122 dev_err(data->dev, "gpiod_to_irq: %d\n", data->irqnr); in ping_read()
123 mutex_unlock(&data->lock); in ping_read()
124 return data->irqnr; in ping_read()
127 ret = request_irq(data->irqnr, ping_handle_irq, in ping_read()
129 pdev->name, indio_dev); in ping_read()
131 dev_err(data->dev, "request_irq: %d\n", ret); in ping_read()
132 mutex_unlock(&data->lock); in ping_read()
137 ret = wait_for_completion_killable_timeout(&data->rising, HZ/50); in ping_read()
141 ret = -ETIMEDOUT; in ping_read()
146 ret = wait_for_completion_killable_timeout(&data->falling, HZ/20); in ping_read()
150 ret = -ETIMEDOUT; in ping_read()
154 ktime_dt = ktime_sub(data->ts_falling, data->ts_rising); in ping_read()
156 free_irq(data->irqnr, indio_dev); in ping_read()
158 ret = gpiod_direction_output(data->gpiod_ping, GPIOD_OUT_LOW); in ping_read()
160 mutex_unlock(&data->lock); in ping_read()
164 mutex_unlock(&data->lock); in ping_read()
167 if (dt_ns > data->cfg->timeout_ns) { in ping_read()
168 dev_dbg(data->dev, "distance out of range: dt=%lldns\n", in ping_read()
170 return -EIO; in ping_read()
176 * read error code of laser ping sensor and give users chance to in ping_read()
179 if (data->cfg->laserping_error) { in ping_read()
181 dev_dbg(data->dev, "target too close or to far\n"); in ping_read()
182 return -EIO; in ping_read()
185 dev_dbg(data->dev, "internal sensor error\n"); in ping_read()
186 return -EIO; in ping_read()
189 dev_dbg(data->dev, "internal sensor timeout\n"); in ping_read()
190 return -EIO; in ping_read()
206 * distance = ------ * ------- = ------------ in ping_read()
219 free_irq(data->irqnr, indio_dev); in ping_read()
220 mutex_unlock(&data->lock); in ping_read()
222 if (gpiod_direction_output(data->gpiod_ping, GPIOD_OUT_LOW)) in ping_read()
223 dev_dbg(data->dev, "error in gpiod_direction_output\n"); in ping_read()
233 if (channel->type != IIO_DISTANCE) in ping_read_raw()
234 return -EINVAL; in ping_read_raw()
252 return -EINVAL; in ping_read_raw()
270 { .compatible = "parallax,ping", .data = &pa_ping_cfg},
279 struct device *dev = &pdev->dev; in ping_probe()
286 return -ENOMEM; in ping_probe()
290 data->dev = dev; in ping_probe()
291 data->cfg = of_device_get_match_data(dev); in ping_probe()
293 mutex_init(&data->lock); in ping_probe()
294 init_completion(&data->rising); in ping_probe()
295 init_completion(&data->falling); in ping_probe()
297 data->gpiod_ping = devm_gpiod_get(dev, "ping", GPIOD_OUT_LOW); in ping_probe()
298 if (IS_ERR(data->gpiod_ping)) { in ping_probe()
299 dev_err(dev, "failed to get ping-gpios: err=%ld\n", in ping_probe()
300 PTR_ERR(data->gpiod_ping)); in ping_probe()
301 return PTR_ERR(data->gpiod_ping); in ping_probe()
304 if (gpiod_cansleep(data->gpiod_ping)) { in ping_probe()
305 dev_err(data->dev, "cansleep-GPIOs not supported\n"); in ping_probe()
306 return -ENODEV; in ping_probe()
311 indio_dev->name = "ping"; in ping_probe()
312 indio_dev->info = &ping_iio_info; in ping_probe()
313 indio_dev->modes = INDIO_DIRECT_MODE; in ping_probe()
314 indio_dev->channels = ping_chan_spec; in ping_probe()
315 indio_dev->num_channels = ARRAY_SIZE(ping_chan_spec); in ping_probe()
323 .name = "ping-gpio",
330 MODULE_AUTHOR("Andreas Klinger <ak@it-klinger.de>");
331 MODULE_DESCRIPTION("PING sensors for distance measuring using one GPIOs");
333 MODULE_ALIAS("platform:ping");