xref: /openbmc/linux/drivers/iio/proximity/srf04.c (revision 1364262c)
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)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 
srf04_pm_runtime_suspend(struct device * dev)362*1364262cSJonathan Cameron static int  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 
srf04_pm_runtime_resume(struct device * dev)374*1364262cSJonathan Cameron static int 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 = {
388*1364262cSJonathan Cameron 	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,
398*1364262cSJonathan Cameron 		.pm		= pm_ptr(&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