1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2feda2840SAndreas Klinger /* 3feda2840SAndreas Klinger * SRF04: ultrasonic sensor for distance measuring by using GPIOs 4feda2840SAndreas Klinger * 5feda2840SAndreas Klinger * Copyright (c) 2017 Andreas Klinger <ak@it-klinger.de> 6feda2840SAndreas Klinger * 7feda2840SAndreas Klinger * For details about the device see: 83593cd53SAlexander A. Klimov * https://www.robot-electronics.co.uk/htm/srf04tech.htm 9feda2840SAndreas Klinger * 10feda2840SAndreas Klinger * the measurement cycle as timing diagram looks like: 11feda2840SAndreas Klinger * 12feda2840SAndreas Klinger * +---+ 13feda2840SAndreas Klinger * GPIO | | 14feda2840SAndreas Klinger * trig: --+ +------------------------------------------------------ 15feda2840SAndreas Klinger * ^ ^ 16feda2840SAndreas Klinger * |<->| 17bb208037SAndreas Klinger * udelay(trigger_pulse_us) 18feda2840SAndreas Klinger * 19feda2840SAndreas Klinger * ultra +-+ +-+ +-+ 20feda2840SAndreas Klinger * sonic | | | | | | 21feda2840SAndreas Klinger * burst: ---------+ +-+ +-+ +----------------------------------------- 22feda2840SAndreas Klinger * . 23feda2840SAndreas Klinger * ultra . +-+ +-+ +-+ 24feda2840SAndreas Klinger * sonic . | | | | | | 25feda2840SAndreas Klinger * echo: ----------------------------------+ +-+ +-+ +---------------- 26feda2840SAndreas Klinger * . . 27feda2840SAndreas Klinger * +------------------------+ 28feda2840SAndreas Klinger * GPIO | | 29feda2840SAndreas Klinger * echo: -------------------+ +--------------- 30feda2840SAndreas Klinger * ^ ^ 31feda2840SAndreas Klinger * interrupt interrupt 32feda2840SAndreas Klinger * (ts_rising) (ts_falling) 33feda2840SAndreas Klinger * |<---------------------->| 34feda2840SAndreas Klinger * pulse time measured 35feda2840SAndreas Klinger * --> one round trip of ultra sonic waves 36feda2840SAndreas Klinger */ 37feda2840SAndreas Klinger #include <linux/err.h> 38feda2840SAndreas Klinger #include <linux/gpio/consumer.h> 39feda2840SAndreas Klinger #include <linux/kernel.h> 40*cffc293dSAndy Shevchenko #include <linux/mod_devicetable.h> 41feda2840SAndreas Klinger #include <linux/module.h> 42feda2840SAndreas Klinger #include <linux/platform_device.h> 43feda2840SAndreas Klinger #include <linux/property.h> 44feda2840SAndreas Klinger #include <linux/sched.h> 45feda2840SAndreas Klinger #include <linux/interrupt.h> 46feda2840SAndreas Klinger #include <linux/delay.h> 472251157bSAndreas Klinger #include <linux/pm_runtime.h> 48feda2840SAndreas Klinger #include <linux/iio/iio.h> 49feda2840SAndreas Klinger #include <linux/iio/sysfs.h> 50feda2840SAndreas Klinger 51bb208037SAndreas Klinger struct srf04_cfg { 52bb208037SAndreas Klinger unsigned long trigger_pulse_us; 53bb208037SAndreas Klinger }; 54bb208037SAndreas Klinger 55feda2840SAndreas Klinger struct srf04_data { 56feda2840SAndreas Klinger struct device *dev; 57feda2840SAndreas Klinger struct gpio_desc *gpiod_trig; 58feda2840SAndreas Klinger struct gpio_desc *gpiod_echo; 592251157bSAndreas Klinger struct gpio_desc *gpiod_power; 60feda2840SAndreas Klinger struct mutex lock; 61feda2840SAndreas Klinger int irqnr; 62feda2840SAndreas Klinger ktime_t ts_rising; 63feda2840SAndreas Klinger ktime_t ts_falling; 64feda2840SAndreas Klinger struct completion rising; 65feda2840SAndreas Klinger struct completion falling; 66bb208037SAndreas Klinger const struct srf04_cfg *cfg; 672251157bSAndreas Klinger int startup_time_ms; 68bb208037SAndreas Klinger }; 69bb208037SAndreas Klinger 70bb208037SAndreas Klinger static const struct srf04_cfg srf04_cfg = { 71bb208037SAndreas Klinger .trigger_pulse_us = 10, 72bb208037SAndreas Klinger }; 73bb208037SAndreas Klinger 74bb208037SAndreas Klinger static const struct srf04_cfg mb_lv_cfg = { 75bb208037SAndreas Klinger .trigger_pulse_us = 20, 76feda2840SAndreas Klinger }; 77feda2840SAndreas Klinger 78feda2840SAndreas Klinger static irqreturn_t srf04_handle_irq(int irq, void *dev_id) 79feda2840SAndreas Klinger { 80feda2840SAndreas Klinger struct iio_dev *indio_dev = dev_id; 81feda2840SAndreas Klinger struct srf04_data *data = iio_priv(indio_dev); 82feda2840SAndreas Klinger ktime_t now = ktime_get(); 83feda2840SAndreas Klinger 84feda2840SAndreas Klinger if (gpiod_get_value(data->gpiod_echo)) { 85feda2840SAndreas Klinger data->ts_rising = now; 86feda2840SAndreas Klinger complete(&data->rising); 87feda2840SAndreas Klinger } else { 88feda2840SAndreas Klinger data->ts_falling = now; 89feda2840SAndreas Klinger complete(&data->falling); 90feda2840SAndreas Klinger } 91feda2840SAndreas Klinger 92feda2840SAndreas Klinger return IRQ_HANDLED; 93feda2840SAndreas Klinger } 94feda2840SAndreas Klinger 95feda2840SAndreas Klinger static int srf04_read(struct srf04_data *data) 96feda2840SAndreas Klinger { 97feda2840SAndreas Klinger int ret; 98feda2840SAndreas Klinger ktime_t ktime_dt; 99feda2840SAndreas Klinger u64 dt_ns; 100feda2840SAndreas Klinger u32 time_ns, distance_mm; 101feda2840SAndreas Klinger 1029009a732SJonathan Cameron if (data->gpiod_power) { 1039009a732SJonathan Cameron ret = pm_runtime_resume_and_get(data->dev); 1049009a732SJonathan Cameron if (ret < 0) 1059009a732SJonathan Cameron return ret; 1069009a732SJonathan Cameron } 107feda2840SAndreas Klinger /* 108feda2840SAndreas Klinger * just one read-echo-cycle can take place at a time 109feda2840SAndreas Klinger * ==> lock against concurrent reading calls 110feda2840SAndreas Klinger */ 111feda2840SAndreas Klinger mutex_lock(&data->lock); 112feda2840SAndreas Klinger 113feda2840SAndreas Klinger reinit_completion(&data->rising); 114feda2840SAndreas Klinger reinit_completion(&data->falling); 115feda2840SAndreas Klinger 116feda2840SAndreas Klinger gpiod_set_value(data->gpiod_trig, 1); 117bb208037SAndreas Klinger udelay(data->cfg->trigger_pulse_us); 118feda2840SAndreas Klinger gpiod_set_value(data->gpiod_trig, 0); 119feda2840SAndreas Klinger 1202251157bSAndreas Klinger if (data->gpiod_power) { 1212251157bSAndreas Klinger pm_runtime_mark_last_busy(data->dev); 1222251157bSAndreas Klinger pm_runtime_put_autosuspend(data->dev); 1232251157bSAndreas Klinger } 1242251157bSAndreas Klinger 125431f7667SAndreas Klinger /* it should not take more than 20 ms until echo is rising */ 126feda2840SAndreas Klinger ret = wait_for_completion_killable_timeout(&data->rising, HZ/50); 127feda2840SAndreas Klinger if (ret < 0) { 128feda2840SAndreas Klinger mutex_unlock(&data->lock); 129feda2840SAndreas Klinger return ret; 130feda2840SAndreas Klinger } else if (ret == 0) { 131feda2840SAndreas Klinger mutex_unlock(&data->lock); 132feda2840SAndreas Klinger return -ETIMEDOUT; 133feda2840SAndreas Klinger } 134feda2840SAndreas Klinger 135431f7667SAndreas Klinger /* it cannot take more than 50 ms until echo is falling */ 136431f7667SAndreas Klinger ret = wait_for_completion_killable_timeout(&data->falling, HZ/20); 137feda2840SAndreas Klinger if (ret < 0) { 138feda2840SAndreas Klinger mutex_unlock(&data->lock); 139feda2840SAndreas Klinger return ret; 140feda2840SAndreas Klinger } else if (ret == 0) { 141feda2840SAndreas Klinger mutex_unlock(&data->lock); 142feda2840SAndreas Klinger return -ETIMEDOUT; 143feda2840SAndreas Klinger } 144feda2840SAndreas Klinger 145feda2840SAndreas Klinger ktime_dt = ktime_sub(data->ts_falling, data->ts_rising); 146feda2840SAndreas Klinger 147feda2840SAndreas Klinger mutex_unlock(&data->lock); 148feda2840SAndreas Klinger 149feda2840SAndreas Klinger dt_ns = ktime_to_ns(ktime_dt); 150feda2840SAndreas Klinger /* 151431f7667SAndreas Klinger * measuring more than 6,45 meters is beyond the capabilities of 152431f7667SAndreas Klinger * the supported sensors 153feda2840SAndreas Klinger * ==> filter out invalid results for not measuring echos of 154feda2840SAndreas Klinger * another us sensor 155feda2840SAndreas Klinger * 156feda2840SAndreas Klinger * formula: 157431f7667SAndreas Klinger * distance 6,45 * 2 m 158431f7667SAndreas Klinger * time = ---------- = ------------ = 40438871 ns 159feda2840SAndreas Klinger * speed 319 m/s 160feda2840SAndreas Klinger * 161feda2840SAndreas Klinger * using a minimum speed at -20 °C of 319 m/s 162feda2840SAndreas Klinger */ 163431f7667SAndreas Klinger if (dt_ns > 40438871) 164feda2840SAndreas Klinger return -EIO; 165feda2840SAndreas Klinger 166feda2840SAndreas Klinger time_ns = dt_ns; 167feda2840SAndreas Klinger 168feda2840SAndreas Klinger /* 169feda2840SAndreas Klinger * the speed as function of the temperature is approximately: 170feda2840SAndreas Klinger * 171feda2840SAndreas Klinger * speed = 331,5 + 0,6 * Temp 172feda2840SAndreas Klinger * with Temp in °C 173feda2840SAndreas Klinger * and speed in m/s 174feda2840SAndreas Klinger * 175431f7667SAndreas Klinger * use 343,5 m/s as ultrasonic speed at 20 °C here in absence of the 176feda2840SAndreas Klinger * temperature 177feda2840SAndreas Klinger * 178feda2840SAndreas Klinger * therefore: 179431f7667SAndreas Klinger * time 343,5 time * 106 180431f7667SAndreas Klinger * distance = ------ * ------- = ------------ 181431f7667SAndreas Klinger * 10^6 2 617176 182feda2840SAndreas Klinger * with time in ns 183feda2840SAndreas Klinger * and distance in mm (one way) 184feda2840SAndreas Klinger * 185431f7667SAndreas Klinger * because we limit to 6,45 meters the multiplication with 106 just 186feda2840SAndreas Klinger * fits into 32 bit 187feda2840SAndreas Klinger */ 188431f7667SAndreas Klinger distance_mm = time_ns * 106 / 617176; 189feda2840SAndreas Klinger 190feda2840SAndreas Klinger return distance_mm; 191feda2840SAndreas Klinger } 192feda2840SAndreas Klinger 193feda2840SAndreas Klinger static int srf04_read_raw(struct iio_dev *indio_dev, 194feda2840SAndreas Klinger struct iio_chan_spec const *channel, int *val, 195feda2840SAndreas Klinger int *val2, long info) 196feda2840SAndreas Klinger { 197feda2840SAndreas Klinger struct srf04_data *data = iio_priv(indio_dev); 198feda2840SAndreas Klinger int ret; 199feda2840SAndreas Klinger 200feda2840SAndreas Klinger if (channel->type != IIO_DISTANCE) 201feda2840SAndreas Klinger return -EINVAL; 202feda2840SAndreas Klinger 203feda2840SAndreas Klinger switch (info) { 204feda2840SAndreas Klinger case IIO_CHAN_INFO_RAW: 205feda2840SAndreas Klinger ret = srf04_read(data); 206feda2840SAndreas Klinger if (ret < 0) 207feda2840SAndreas Klinger return ret; 208feda2840SAndreas Klinger *val = ret; 209feda2840SAndreas Klinger return IIO_VAL_INT; 210feda2840SAndreas Klinger case IIO_CHAN_INFO_SCALE: 211feda2840SAndreas Klinger /* 212feda2840SAndreas Klinger * theoretical maximum resolution is 3 mm 213feda2840SAndreas Klinger * 1 LSB is 1 mm 214feda2840SAndreas Klinger */ 215feda2840SAndreas Klinger *val = 0; 216feda2840SAndreas Klinger *val2 = 1000; 217feda2840SAndreas Klinger return IIO_VAL_INT_PLUS_MICRO; 218feda2840SAndreas Klinger default: 219feda2840SAndreas Klinger return -EINVAL; 220feda2840SAndreas Klinger } 221feda2840SAndreas Klinger } 222feda2840SAndreas Klinger 223feda2840SAndreas Klinger static const struct iio_info srf04_iio_info = { 224feda2840SAndreas Klinger .read_raw = srf04_read_raw, 225feda2840SAndreas Klinger }; 226feda2840SAndreas Klinger 227feda2840SAndreas Klinger static const struct iio_chan_spec srf04_chan_spec[] = { 228feda2840SAndreas Klinger { 229feda2840SAndreas Klinger .type = IIO_DISTANCE, 230feda2840SAndreas Klinger .info_mask_separate = 231feda2840SAndreas Klinger BIT(IIO_CHAN_INFO_RAW) | 232feda2840SAndreas Klinger BIT(IIO_CHAN_INFO_SCALE), 233feda2840SAndreas Klinger }, 234feda2840SAndreas Klinger }; 235feda2840SAndreas Klinger 236bb208037SAndreas Klinger static const struct of_device_id of_srf04_match[] = { 237bb208037SAndreas Klinger { .compatible = "devantech,srf04", .data = &srf04_cfg }, 238bb208037SAndreas Klinger { .compatible = "maxbotix,mb1000", .data = &mb_lv_cfg }, 239bb208037SAndreas Klinger { .compatible = "maxbotix,mb1010", .data = &mb_lv_cfg }, 240bb208037SAndreas Klinger { .compatible = "maxbotix,mb1020", .data = &mb_lv_cfg }, 241bb208037SAndreas Klinger { .compatible = "maxbotix,mb1030", .data = &mb_lv_cfg }, 242bb208037SAndreas Klinger { .compatible = "maxbotix,mb1040", .data = &mb_lv_cfg }, 243bb208037SAndreas Klinger {}, 244bb208037SAndreas Klinger }; 245bb208037SAndreas Klinger 246bb208037SAndreas Klinger MODULE_DEVICE_TABLE(of, of_srf04_match); 247bb208037SAndreas Klinger 248feda2840SAndreas Klinger static int srf04_probe(struct platform_device *pdev) 249feda2840SAndreas Klinger { 250feda2840SAndreas Klinger struct device *dev = &pdev->dev; 251feda2840SAndreas Klinger struct srf04_data *data; 252feda2840SAndreas Klinger struct iio_dev *indio_dev; 253feda2840SAndreas Klinger int ret; 254feda2840SAndreas Klinger 255feda2840SAndreas Klinger indio_dev = devm_iio_device_alloc(dev, sizeof(struct srf04_data)); 256feda2840SAndreas Klinger if (!indio_dev) { 257feda2840SAndreas Klinger dev_err(dev, "failed to allocate IIO device\n"); 258feda2840SAndreas Klinger return -ENOMEM; 259feda2840SAndreas Klinger } 260feda2840SAndreas Klinger 261feda2840SAndreas Klinger data = iio_priv(indio_dev); 262feda2840SAndreas Klinger data->dev = dev; 263*cffc293dSAndy Shevchenko data->cfg = device_get_match_data(dev); 264feda2840SAndreas Klinger 265feda2840SAndreas Klinger mutex_init(&data->lock); 266feda2840SAndreas Klinger init_completion(&data->rising); 267feda2840SAndreas Klinger init_completion(&data->falling); 268feda2840SAndreas Klinger 269feda2840SAndreas Klinger data->gpiod_trig = devm_gpiod_get(dev, "trig", GPIOD_OUT_LOW); 270feda2840SAndreas Klinger if (IS_ERR(data->gpiod_trig)) { 271feda2840SAndreas Klinger dev_err(dev, "failed to get trig-gpios: err=%ld\n", 272feda2840SAndreas Klinger PTR_ERR(data->gpiod_trig)); 273feda2840SAndreas Klinger return PTR_ERR(data->gpiod_trig); 274feda2840SAndreas Klinger } 275feda2840SAndreas Klinger 276feda2840SAndreas Klinger data->gpiod_echo = devm_gpiod_get(dev, "echo", GPIOD_IN); 277feda2840SAndreas Klinger if (IS_ERR(data->gpiod_echo)) { 278feda2840SAndreas Klinger dev_err(dev, "failed to get echo-gpios: err=%ld\n", 279feda2840SAndreas Klinger PTR_ERR(data->gpiod_echo)); 280feda2840SAndreas Klinger return PTR_ERR(data->gpiod_echo); 281feda2840SAndreas Klinger } 282feda2840SAndreas Klinger 2832251157bSAndreas Klinger data->gpiod_power = devm_gpiod_get_optional(dev, "power", 2842251157bSAndreas Klinger GPIOD_OUT_LOW); 2852251157bSAndreas Klinger if (IS_ERR(data->gpiod_power)) { 2862251157bSAndreas Klinger dev_err(dev, "failed to get power-gpios: err=%ld\n", 2872251157bSAndreas Klinger PTR_ERR(data->gpiod_power)); 2882251157bSAndreas Klinger return PTR_ERR(data->gpiod_power); 2892251157bSAndreas Klinger } 2902251157bSAndreas Klinger if (data->gpiod_power) { 2912251157bSAndreas Klinger data->startup_time_ms = 100; 292*cffc293dSAndy Shevchenko device_property_read_u32(dev, "startup-time-ms", &data->startup_time_ms); 2932251157bSAndreas Klinger dev_dbg(dev, "using power gpio: startup-time-ms=%d\n", 2942251157bSAndreas Klinger data->startup_time_ms); 2952251157bSAndreas Klinger } 2962251157bSAndreas Klinger 297feda2840SAndreas Klinger if (gpiod_cansleep(data->gpiod_echo)) { 298feda2840SAndreas Klinger dev_err(data->dev, "cansleep-GPIOs not supported\n"); 299feda2840SAndreas Klinger return -ENODEV; 300feda2840SAndreas Klinger } 301feda2840SAndreas Klinger 302feda2840SAndreas Klinger data->irqnr = gpiod_to_irq(data->gpiod_echo); 303feda2840SAndreas Klinger if (data->irqnr < 0) { 304feda2840SAndreas Klinger dev_err(data->dev, "gpiod_to_irq: %d\n", data->irqnr); 305feda2840SAndreas Klinger return data->irqnr; 306feda2840SAndreas Klinger } 307feda2840SAndreas Klinger 308feda2840SAndreas Klinger ret = devm_request_irq(dev, data->irqnr, srf04_handle_irq, 309feda2840SAndreas Klinger IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 310feda2840SAndreas Klinger pdev->name, indio_dev); 311feda2840SAndreas Klinger if (ret < 0) { 312feda2840SAndreas Klinger dev_err(data->dev, "request_irq: %d\n", ret); 313feda2840SAndreas Klinger return ret; 314feda2840SAndreas Klinger } 315feda2840SAndreas Klinger 316feda2840SAndreas Klinger platform_set_drvdata(pdev, indio_dev); 317feda2840SAndreas Klinger 318feda2840SAndreas Klinger indio_dev->name = "srf04"; 319feda2840SAndreas Klinger indio_dev->info = &srf04_iio_info; 320feda2840SAndreas Klinger indio_dev->modes = INDIO_DIRECT_MODE; 321feda2840SAndreas Klinger indio_dev->channels = srf04_chan_spec; 322feda2840SAndreas Klinger indio_dev->num_channels = ARRAY_SIZE(srf04_chan_spec); 323feda2840SAndreas Klinger 3242251157bSAndreas Klinger ret = iio_device_register(indio_dev); 3252251157bSAndreas Klinger if (ret < 0) { 3262251157bSAndreas Klinger dev_err(data->dev, "iio_device_register: %d\n", ret); 3272251157bSAndreas Klinger return ret; 328feda2840SAndreas Klinger } 329feda2840SAndreas Klinger 3302251157bSAndreas Klinger if (data->gpiod_power) { 3312251157bSAndreas Klinger pm_runtime_set_autosuspend_delay(data->dev, 1000); 3322251157bSAndreas Klinger pm_runtime_use_autosuspend(data->dev); 3332251157bSAndreas Klinger 3342251157bSAndreas Klinger ret = pm_runtime_set_active(data->dev); 3352251157bSAndreas Klinger if (ret) { 3362251157bSAndreas Klinger dev_err(data->dev, "pm_runtime_set_active: %d\n", ret); 3372251157bSAndreas Klinger iio_device_unregister(indio_dev); 3382251157bSAndreas Klinger } 3392251157bSAndreas Klinger 3402251157bSAndreas Klinger pm_runtime_enable(data->dev); 3412251157bSAndreas Klinger pm_runtime_idle(data->dev); 3422251157bSAndreas Klinger } 3432251157bSAndreas Klinger 3442251157bSAndreas Klinger return ret; 3452251157bSAndreas Klinger } 3462251157bSAndreas Klinger 3472251157bSAndreas Klinger static int srf04_remove(struct platform_device *pdev) 3482251157bSAndreas Klinger { 3492251157bSAndreas Klinger struct iio_dev *indio_dev = platform_get_drvdata(pdev); 3502251157bSAndreas Klinger struct srf04_data *data = iio_priv(indio_dev); 3512251157bSAndreas Klinger 3522251157bSAndreas Klinger iio_device_unregister(indio_dev); 3532251157bSAndreas Klinger 3542251157bSAndreas Klinger if (data->gpiod_power) { 3552251157bSAndreas Klinger pm_runtime_disable(data->dev); 3562251157bSAndreas Klinger pm_runtime_set_suspended(data->dev); 3572251157bSAndreas Klinger } 3582251157bSAndreas Klinger 3592251157bSAndreas Klinger return 0; 3602251157bSAndreas Klinger } 3612251157bSAndreas Klinger 3622251157bSAndreas Klinger static int __maybe_unused srf04_pm_runtime_suspend(struct device *dev) 3632251157bSAndreas Klinger { 3642251157bSAndreas Klinger struct platform_device *pdev = container_of(dev, 3652251157bSAndreas Klinger struct platform_device, dev); 3662251157bSAndreas Klinger struct iio_dev *indio_dev = platform_get_drvdata(pdev); 3672251157bSAndreas Klinger struct srf04_data *data = iio_priv(indio_dev); 3682251157bSAndreas Klinger 3692251157bSAndreas Klinger gpiod_set_value(data->gpiod_power, 0); 3702251157bSAndreas Klinger 3712251157bSAndreas Klinger return 0; 3722251157bSAndreas Klinger } 3732251157bSAndreas Klinger 3742251157bSAndreas Klinger static int __maybe_unused srf04_pm_runtime_resume(struct device *dev) 3752251157bSAndreas Klinger { 3762251157bSAndreas Klinger struct platform_device *pdev = container_of(dev, 3772251157bSAndreas Klinger struct platform_device, dev); 3782251157bSAndreas Klinger struct iio_dev *indio_dev = platform_get_drvdata(pdev); 3792251157bSAndreas Klinger struct srf04_data *data = iio_priv(indio_dev); 3802251157bSAndreas Klinger 3812251157bSAndreas Klinger gpiod_set_value(data->gpiod_power, 1); 3822251157bSAndreas Klinger msleep(data->startup_time_ms); 3832251157bSAndreas Klinger 3842251157bSAndreas Klinger return 0; 3852251157bSAndreas Klinger } 3862251157bSAndreas Klinger 3872251157bSAndreas Klinger static const struct dev_pm_ops srf04_pm_ops = { 3882251157bSAndreas Klinger SET_RUNTIME_PM_OPS(srf04_pm_runtime_suspend, 3892251157bSAndreas Klinger srf04_pm_runtime_resume, NULL) 3902251157bSAndreas Klinger }; 3912251157bSAndreas Klinger 392feda2840SAndreas Klinger static struct platform_driver srf04_driver = { 393feda2840SAndreas Klinger .probe = srf04_probe, 3942251157bSAndreas Klinger .remove = srf04_remove, 395feda2840SAndreas Klinger .driver = { 396feda2840SAndreas Klinger .name = "srf04-gpio", 397feda2840SAndreas Klinger .of_match_table = of_srf04_match, 3982251157bSAndreas Klinger .pm = &srf04_pm_ops, 399feda2840SAndreas Klinger }, 400feda2840SAndreas Klinger }; 401feda2840SAndreas Klinger 402feda2840SAndreas Klinger module_platform_driver(srf04_driver); 403feda2840SAndreas Klinger 404feda2840SAndreas Klinger MODULE_AUTHOR("Andreas Klinger <ak@it-klinger.de>"); 405feda2840SAndreas Klinger MODULE_DESCRIPTION("SRF04 ultrasonic sensor for distance measuring using GPIOs"); 406feda2840SAndreas Klinger MODULE_LICENSE("GPL"); 407feda2840SAndreas Klinger MODULE_ALIAS("platform:srf04"); 408