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