forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/drivers/iio/proximity/srf04.c
....@@ -1,20 +1,11 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * SRF04: ultrasonic sensor for distance measuring by using GPIOs
34 *
45 * Copyright (c) 2017 Andreas Klinger <ak@it-klinger.de>
56 *
6
- * This program is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License as published by
8
- * the Free Software Foundation; either version 2 of the License, or
9
- * (at your option) any later version.
10
- *
11
- * This program is distributed in the hope that it will be useful,
12
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- * GNU General Public License for more details.
15
- *
167 * For details about the device see:
17
- * http://www.robot-electronics.co.uk/htm/srf04tech.htm
8
+ * https://www.robot-electronics.co.uk/htm/srf04tech.htm
189 *
1910 * the measurement cycle as timing diagram looks like:
2011 *
....@@ -23,7 +14,7 @@
2314 * trig: --+ +------------------------------------------------------
2415 * ^ ^
2516 * |<->|
26
- * udelay(10)
17
+ * udelay(trigger_pulse_us)
2718 *
2819 * ultra +-+ +-+ +-+
2920 * sonic | | | | | |
....@@ -48,24 +39,41 @@
4839 #include <linux/kernel.h>
4940 #include <linux/module.h>
5041 #include <linux/of.h>
42
+#include <linux/of_device.h>
5143 #include <linux/platform_device.h>
5244 #include <linux/property.h>
5345 #include <linux/sched.h>
5446 #include <linux/interrupt.h>
5547 #include <linux/delay.h>
48
+#include <linux/pm_runtime.h>
5649 #include <linux/iio/iio.h>
5750 #include <linux/iio/sysfs.h>
51
+
52
+struct srf04_cfg {
53
+ unsigned long trigger_pulse_us;
54
+};
5855
5956 struct srf04_data {
6057 struct device *dev;
6158 struct gpio_desc *gpiod_trig;
6259 struct gpio_desc *gpiod_echo;
60
+ struct gpio_desc *gpiod_power;
6361 struct mutex lock;
6462 int irqnr;
6563 ktime_t ts_rising;
6664 ktime_t ts_falling;
6765 struct completion rising;
6866 struct completion falling;
67
+ const struct srf04_cfg *cfg;
68
+ int startup_time_ms;
69
+};
70
+
71
+static const struct srf04_cfg srf04_cfg = {
72
+ .trigger_pulse_us = 10,
73
+};
74
+
75
+static const struct srf04_cfg mb_lv_cfg = {
76
+ .trigger_pulse_us = 20,
6977 };
7078
7179 static irqreturn_t srf04_handle_irq(int irq, void *dev_id)
....@@ -92,6 +100,9 @@
92100 u64 dt_ns;
93101 u32 time_ns, distance_mm;
94102
103
+ if (data->gpiod_power)
104
+ pm_runtime_get_sync(data->dev);
105
+
95106 /*
96107 * just one read-echo-cycle can take place at a time
97108 * ==> lock against concurrent reading calls
....@@ -102,8 +113,13 @@
102113 reinit_completion(&data->falling);
103114
104115 gpiod_set_value(data->gpiod_trig, 1);
105
- udelay(10);
116
+ udelay(data->cfg->trigger_pulse_us);
106117 gpiod_set_value(data->gpiod_trig, 0);
118
+
119
+ if (data->gpiod_power) {
120
+ pm_runtime_mark_last_busy(data->dev);
121
+ pm_runtime_put_autosuspend(data->dev);
122
+ }
107123
108124 /* it should not take more than 20 ms until echo is rising */
109125 ret = wait_for_completion_killable_timeout(&data->rising, HZ/50);
....@@ -216,6 +232,18 @@
216232 },
217233 };
218234
235
+static const struct of_device_id of_srf04_match[] = {
236
+ { .compatible = "devantech,srf04", .data = &srf04_cfg},
237
+ { .compatible = "maxbotix,mb1000", .data = &mb_lv_cfg},
238
+ { .compatible = "maxbotix,mb1010", .data = &mb_lv_cfg},
239
+ { .compatible = "maxbotix,mb1020", .data = &mb_lv_cfg},
240
+ { .compatible = "maxbotix,mb1030", .data = &mb_lv_cfg},
241
+ { .compatible = "maxbotix,mb1040", .data = &mb_lv_cfg},
242
+ {},
243
+};
244
+
245
+MODULE_DEVICE_TABLE(of, of_srf04_match);
246
+
219247 static int srf04_probe(struct platform_device *pdev)
220248 {
221249 struct device *dev = &pdev->dev;
....@@ -231,6 +259,7 @@
231259
232260 data = iio_priv(indio_dev);
233261 data->dev = dev;
262
+ data->cfg = of_match_device(of_srf04_match, dev)->data;
234263
235264 mutex_init(&data->lock);
236265 init_completion(&data->rising);
....@@ -248,6 +277,22 @@
248277 dev_err(dev, "failed to get echo-gpios: err=%ld\n",
249278 PTR_ERR(data->gpiod_echo));
250279 return PTR_ERR(data->gpiod_echo);
280
+ }
281
+
282
+ data->gpiod_power = devm_gpiod_get_optional(dev, "power",
283
+ GPIOD_OUT_LOW);
284
+ if (IS_ERR(data->gpiod_power)) {
285
+ dev_err(dev, "failed to get power-gpios: err=%ld\n",
286
+ PTR_ERR(data->gpiod_power));
287
+ return PTR_ERR(data->gpiod_power);
288
+ }
289
+ if (data->gpiod_power) {
290
+
291
+ if (of_property_read_u32(dev->of_node, "startup-time-ms",
292
+ &data->startup_time_ms))
293
+ data->startup_time_ms = 100;
294
+ dev_dbg(dev, "using power gpio: startup-time-ms=%d\n",
295
+ data->startup_time_ms);
251296 }
252297
253298 if (gpiod_cansleep(data->gpiod_echo)) {
....@@ -272,27 +317,86 @@
272317 platform_set_drvdata(pdev, indio_dev);
273318
274319 indio_dev->name = "srf04";
275
- indio_dev->dev.parent = &pdev->dev;
276320 indio_dev->info = &srf04_iio_info;
277321 indio_dev->modes = INDIO_DIRECT_MODE;
278322 indio_dev->channels = srf04_chan_spec;
279323 indio_dev->num_channels = ARRAY_SIZE(srf04_chan_spec);
280324
281
- return devm_iio_device_register(dev, indio_dev);
325
+ ret = iio_device_register(indio_dev);
326
+ if (ret < 0) {
327
+ dev_err(data->dev, "iio_device_register: %d\n", ret);
328
+ return ret;
329
+ }
330
+
331
+ if (data->gpiod_power) {
332
+ pm_runtime_set_autosuspend_delay(data->dev, 1000);
333
+ pm_runtime_use_autosuspend(data->dev);
334
+
335
+ ret = pm_runtime_set_active(data->dev);
336
+ if (ret) {
337
+ dev_err(data->dev, "pm_runtime_set_active: %d\n", ret);
338
+ iio_device_unregister(indio_dev);
339
+ }
340
+
341
+ pm_runtime_enable(data->dev);
342
+ pm_runtime_idle(data->dev);
343
+ }
344
+
345
+ return ret;
282346 }
283347
284
-static const struct of_device_id of_srf04_match[] = {
285
- { .compatible = "devantech,srf04", },
286
- {},
287
-};
348
+static int srf04_remove(struct platform_device *pdev)
349
+{
350
+ struct iio_dev *indio_dev = platform_get_drvdata(pdev);
351
+ struct srf04_data *data = iio_priv(indio_dev);
288352
289
-MODULE_DEVICE_TABLE(of, of_srf04_match);
353
+ iio_device_unregister(indio_dev);
354
+
355
+ if (data->gpiod_power) {
356
+ pm_runtime_disable(data->dev);
357
+ pm_runtime_set_suspended(data->dev);
358
+ }
359
+
360
+ return 0;
361
+}
362
+
363
+static int __maybe_unused srf04_pm_runtime_suspend(struct device *dev)
364
+{
365
+ struct platform_device *pdev = container_of(dev,
366
+ struct platform_device, dev);
367
+ struct iio_dev *indio_dev = platform_get_drvdata(pdev);
368
+ struct srf04_data *data = iio_priv(indio_dev);
369
+
370
+ gpiod_set_value(data->gpiod_power, 0);
371
+
372
+ return 0;
373
+}
374
+
375
+static int __maybe_unused srf04_pm_runtime_resume(struct device *dev)
376
+{
377
+ struct platform_device *pdev = container_of(dev,
378
+ struct platform_device, dev);
379
+ struct iio_dev *indio_dev = platform_get_drvdata(pdev);
380
+ struct srf04_data *data = iio_priv(indio_dev);
381
+
382
+ gpiod_set_value(data->gpiod_power, 1);
383
+ msleep(data->startup_time_ms);
384
+
385
+ return 0;
386
+}
387
+
388
+static const struct dev_pm_ops srf04_pm_ops = {
389
+ SET_RUNTIME_PM_OPS(srf04_pm_runtime_suspend,
390
+ srf04_pm_runtime_resume, NULL)
391
+};
290392
291393 static struct platform_driver srf04_driver = {
292394 .probe = srf04_probe,
395
+ .remove = srf04_remove,
293396 .driver = {
294397 .name = "srf04-gpio",
295398 .of_match_table = of_srf04_match,
399
+ .pm = &srf04_pm_ops,
296400 },
297401 };
298402