^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * PING: ultrasonic sensor for distance measuring by using only one GPIOs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2019 Andreas Klinger <ak@it-klinger.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * For details about the devices see:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * http://parallax.com/sites/default/files/downloads/28041-LaserPING-2m-Rangefinder-Guide.pdf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * http://parallax.com/sites/default/files/downloads/28015-PING-Documentation-v1.6.pdf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * the measurement cycle as timing diagram looks like:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * GPIO ___ ________________________
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * ping: __/ \____________/ \________________
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * ^ ^ ^ ^
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * |<->| interrupt interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * udelay(5) (ts_rising) (ts_falling)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * |<---------------------->|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * . pulse time measured .
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * . --> one round trip of ultra sonic waves
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * ultra . .
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * sonic _ _ _. .
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * burst: _________/ \_/ \_/ \_________________________________________
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * .
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * ultra .
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * sonic _ _ _.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * echo: __________________________________/ \_/ \_/ \________________
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/gpio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/property.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <linux/iio/iio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/iio/sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct ping_cfg {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) unsigned long trigger_pulse_us; /* length of trigger pulse */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) int laserping_error; /* support error code in */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /* pulse width of laser */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /* ping sensors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) s64 timeout_ns; /* timeout in ns */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct ping_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct gpio_desc *gpiod_ping;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) int irqnr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) ktime_t ts_rising;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) ktime_t ts_falling;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct completion rising;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct completion falling;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) const struct ping_cfg *cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) static const struct ping_cfg pa_ping_cfg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) .trigger_pulse_us = 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) .laserping_error = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) .timeout_ns = 18500000, /* 3 meters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static const struct ping_cfg pa_laser_ping_cfg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) .trigger_pulse_us = 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) .laserping_error = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) .timeout_ns = 15500000, /* 2 meters plus error codes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static irqreturn_t ping_handle_irq(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct iio_dev *indio_dev = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct ping_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) ktime_t now = ktime_get();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (gpiod_get_value(data->gpiod_ping)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) data->ts_rising = now;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) complete(&data->rising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) data->ts_falling = now;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) complete(&data->falling);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static int ping_read(struct iio_dev *indio_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct ping_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) ktime_t ktime_dt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) s64 dt_ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) u32 time_ns, distance_mm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) struct platform_device *pdev = to_platform_device(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * just one read-echo-cycle can take place at a time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * ==> lock against concurrent reading calls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) reinit_completion(&data->rising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) reinit_completion(&data->falling);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) gpiod_set_value(data->gpiod_ping, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) udelay(data->cfg->trigger_pulse_us);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) gpiod_set_value(data->gpiod_ping, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) ret = gpiod_direction_input(data->gpiod_ping);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) data->irqnr = gpiod_to_irq(data->gpiod_ping);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (data->irqnr < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) dev_err(data->dev, "gpiod_to_irq: %d\n", data->irqnr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) return data->irqnr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) ret = request_irq(data->irqnr, ping_handle_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) pdev->name, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) dev_err(data->dev, "request_irq: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) /* it should not take more than 20 ms until echo is rising */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) ret = wait_for_completion_killable_timeout(&data->rising, HZ/50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) goto err_reset_direction;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) else if (ret == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) ret = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) goto err_reset_direction;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /* it cannot take more than 50 ms until echo is falling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) ret = wait_for_completion_killable_timeout(&data->falling, HZ/20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) goto err_reset_direction;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) else if (ret == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) ret = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) goto err_reset_direction;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) ktime_dt = ktime_sub(data->ts_falling, data->ts_rising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) free_irq(data->irqnr, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) ret = gpiod_direction_output(data->gpiod_ping, GPIOD_OUT_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) dt_ns = ktime_to_ns(ktime_dt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (dt_ns > data->cfg->timeout_ns) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) dev_dbg(data->dev, "distance out of range: dt=%lldns\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) dt_ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) time_ns = dt_ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * read error code of laser ping sensor and give users chance to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * figure out error by using dynamic debuggging
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (data->cfg->laserping_error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if ((time_ns > 12500000) && (time_ns <= 13500000)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) dev_dbg(data->dev, "target too close or to far\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if ((time_ns > 13500000) && (time_ns <= 14500000)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) dev_dbg(data->dev, "internal sensor error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if ((time_ns > 14500000) && (time_ns <= 15500000)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) dev_dbg(data->dev, "internal sensor timeout\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * the speed as function of the temperature is approximately:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * speed = 331,5 + 0,6 * Temp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * with Temp in °C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * and speed in m/s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) * use 343,5 m/s as ultrasonic speed at 20 °C here in absence of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * temperature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) * therefore:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) * time 343,5 time * 232
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) * distance = ------ * ------- = ------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) * 10^6 2 1350800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * with time in ns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * and distance in mm (one way)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * because we limit to 3 meters the multiplication with 232 just
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * fits into 32 bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) distance_mm = time_ns * 232 / 1350800;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) return distance_mm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) err_reset_direction:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) free_irq(data->irqnr, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (gpiod_direction_output(data->gpiod_ping, GPIOD_OUT_LOW))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) dev_dbg(data->dev, "error in gpiod_direction_output\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) static int ping_read_raw(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) struct iio_chan_spec const *channel, int *val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) int *val2, long info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (channel->type != IIO_DISTANCE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) switch (info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) case IIO_CHAN_INFO_RAW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) ret = ping_read(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) *val = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) return IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) case IIO_CHAN_INFO_SCALE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) * maximum resolution in datasheet is 1 mm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) * 1 LSB is 1 mm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) *val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) *val2 = 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) return IIO_VAL_INT_PLUS_MICRO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) static const struct iio_info ping_iio_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) .read_raw = ping_read_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) static const struct iio_chan_spec ping_chan_spec[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) .type = IIO_DISTANCE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) .info_mask_separate =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) BIT(IIO_CHAN_INFO_RAW) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) BIT(IIO_CHAN_INFO_SCALE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) static const struct of_device_id of_ping_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) { .compatible = "parallax,ping", .data = &pa_ping_cfg},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) { .compatible = "parallax,laserping", .data = &pa_laser_ping_cfg},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) MODULE_DEVICE_TABLE(of, of_ping_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) static int ping_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) struct ping_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) struct iio_dev *indio_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) indio_dev = devm_iio_device_alloc(dev, sizeof(struct ping_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (!indio_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) dev_err(dev, "failed to allocate IIO device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) data->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) data->cfg = of_device_get_match_data(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) mutex_init(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) init_completion(&data->rising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) init_completion(&data->falling);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) data->gpiod_ping = devm_gpiod_get(dev, "ping", GPIOD_OUT_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (IS_ERR(data->gpiod_ping)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) dev_err(dev, "failed to get ping-gpios: err=%ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) PTR_ERR(data->gpiod_ping));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return PTR_ERR(data->gpiod_ping);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (gpiod_cansleep(data->gpiod_ping)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) dev_err(data->dev, "cansleep-GPIOs not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) platform_set_drvdata(pdev, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) indio_dev->name = "ping";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) indio_dev->info = &ping_iio_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) indio_dev->modes = INDIO_DIRECT_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) indio_dev->channels = ping_chan_spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) indio_dev->num_channels = ARRAY_SIZE(ping_chan_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return devm_iio_device_register(dev, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) static struct platform_driver ping_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) .probe = ping_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) .name = "ping-gpio",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) .of_match_table = of_ping_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) module_platform_driver(ping_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) MODULE_AUTHOR("Andreas Klinger <ak@it-klinger.de>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) MODULE_DESCRIPTION("PING sensors for distance measuring using one GPIOs");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) MODULE_ALIAS("platform:ping");