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>
40cffc293dSAndy 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
srf04_handle_irq(int irq,void * dev_id)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
srf04_read(struct srf04_data * data)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
srf04_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * channel,int * val,int * val2,long info)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
srf04_probe(struct platform_device * pdev)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;
263cffc293dSAndy 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;
292cffc293dSAndy 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
srf04_remove(struct platform_device * pdev)347*4abfc97dSUwe Kleine-König static void 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
srf04_pm_runtime_suspend(struct device * dev)3601364262cSJonathan Cameron static int srf04_pm_runtime_suspend(struct device *dev)
3612251157bSAndreas Klinger {
3622251157bSAndreas Klinger struct platform_device *pdev = container_of(dev,
3632251157bSAndreas Klinger struct platform_device, dev);
3642251157bSAndreas Klinger struct iio_dev *indio_dev = platform_get_drvdata(pdev);
3652251157bSAndreas Klinger struct srf04_data *data = iio_priv(indio_dev);
3662251157bSAndreas Klinger
3672251157bSAndreas Klinger gpiod_set_value(data->gpiod_power, 0);
3682251157bSAndreas Klinger
3692251157bSAndreas Klinger return 0;
3702251157bSAndreas Klinger }
3712251157bSAndreas Klinger
srf04_pm_runtime_resume(struct device * dev)3721364262cSJonathan Cameron static int srf04_pm_runtime_resume(struct device *dev)
3732251157bSAndreas Klinger {
3742251157bSAndreas Klinger struct platform_device *pdev = container_of(dev,
3752251157bSAndreas Klinger struct platform_device, dev);
3762251157bSAndreas Klinger struct iio_dev *indio_dev = platform_get_drvdata(pdev);
3772251157bSAndreas Klinger struct srf04_data *data = iio_priv(indio_dev);
3782251157bSAndreas Klinger
3792251157bSAndreas Klinger gpiod_set_value(data->gpiod_power, 1);
3802251157bSAndreas Klinger msleep(data->startup_time_ms);
3812251157bSAndreas Klinger
3822251157bSAndreas Klinger return 0;
3832251157bSAndreas Klinger }
3842251157bSAndreas Klinger
3852251157bSAndreas Klinger static const struct dev_pm_ops srf04_pm_ops = {
3861364262cSJonathan Cameron RUNTIME_PM_OPS(srf04_pm_runtime_suspend,
3872251157bSAndreas Klinger srf04_pm_runtime_resume, NULL)
3882251157bSAndreas Klinger };
3892251157bSAndreas Klinger
390feda2840SAndreas Klinger static struct platform_driver srf04_driver = {
391feda2840SAndreas Klinger .probe = srf04_probe,
392*4abfc97dSUwe Kleine-König .remove_new = srf04_remove,
393feda2840SAndreas Klinger .driver = {
394feda2840SAndreas Klinger .name = "srf04-gpio",
395feda2840SAndreas Klinger .of_match_table = of_srf04_match,
3961364262cSJonathan Cameron .pm = pm_ptr(&srf04_pm_ops),
397feda2840SAndreas Klinger },
398feda2840SAndreas Klinger };
399feda2840SAndreas Klinger
400feda2840SAndreas Klinger module_platform_driver(srf04_driver);
401feda2840SAndreas Klinger
402feda2840SAndreas Klinger MODULE_AUTHOR("Andreas Klinger <ak@it-klinger.de>");
403feda2840SAndreas Klinger MODULE_DESCRIPTION("SRF04 ultrasonic sensor for distance measuring using GPIOs");
404feda2840SAndreas Klinger MODULE_LICENSE("GPL");
405feda2840SAndreas Klinger MODULE_ALIAS("platform:srf04");
406