Gist · 6
/ URL: https://gist.050821.xyz/6
updated file: rcwl96xx1.diff
rcwl96xx1.diff
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | diff --git a/drivers/iio/proximity/Kconfig b/drivers/iio/proximity/Kconfig
index 2ca3b0bc5eba..947cf7a36e75 100644
--- a/drivers/iio/proximity/Kconfig
+++ b/drivers/iio/proximity/Kconfig
@@ -96,6 +96,20 @@ config PING
To compile this driver as a module, choose M here: the
module will be called ping.
+config RCWL96XX
+ tristate "RCWL96XX ultrasonic distance sensor"
+ depends on I2C
+ help
+ Say Y yo build a driver for the RCWL96XX distance sensor chip
+ with I2C module.
+
+ The driver drives the following modules:
+ - RCWL-1005
+ - RCWL-1605
+
+ To compile this driver as a module, choose M here: the
+ module will be called rcwl96xx.
+
config RFD77402
tristate "RFD77402 ToF sensor"
depends on I2C
diff --git a/drivers/iio/proximity/Makefile b/drivers/iio/proximity/Makefile
index f36598380446..a6abe1b7ccc9 100644
--- a/drivers/iio/proximity/Makefile
+++ b/drivers/iio/proximity/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_ISL29501) += isl29501.o
obj-$(CONFIG_LIDAR_LITE_V2) += pulsedlight-lidar-lite-v2.o
obj-$(CONFIG_MB1232) += mb1232.o
obj-$(CONFIG_PING) += ping.o
+obj-$(CONFIG_RCWL96XX) += rcwl96xx.o
obj-$(CONFIG_RFD77402) += rfd77402.o
obj-$(CONFIG_SRF04) += srf04.o
obj-$(CONFIG_SRF08) += srf08.o
diff --git a/drivers/iio/proximity/rcwl96xx.c b/drivers/iio/proximity/rcwl96xx.c
new file mode 100644
index 000000000000..1e8b2a60adfe
--- /dev/null
+++ b/drivers/iio/proximity/rcwl96xx.c
@@ -0,0 +1,139 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * RCWL96xx: ultrasonic distance sensor (i2c)
+ * Support for RCWL96XX chips that drive RCWL-1005, RCWL-1605 modules.
+ *
+ * Copyright (C) 2024 William Goodspeed <goodspeed@mailo.cat>
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/events.h>
+
+#define RCWL96XX_I2C_TRIG_CMD 0x01
+
+struct rcwl96xx_data {
+ struct i2c_client *client;
+ struct mutex lock;
+};
+
+static int rcwl96xx_read(struct rcwl96xx_data *data)
+{
+ u8 raw[3] = { 0 }, cmd[1] = { RCWL96XX_I2C_TRIG_CMD };
+ int ret, distance_mm;
+
+ /* lock against concurrent reading calls */
+ mutex_lock(&data->lock);
+
+ ret = i2c_master_send(data->client, cmd, 1);
+ if (ret < 0) {
+ mutex_unlock(&data->lock);
+ return ret;
+ }
+
+ /* Maximum delay for measurement: 100mS */
+ msleep(100);
+
+ ret = i2c_master_recv(data->client, raw, 3);
+ if (ret < 0) {
+ mutex_unlock(&data->lock);
+ return ret;
+ } else if (ret < 3) {
+ mutex_unlock(&data->lock);
+ return -ENODATA;
+ }
+
+ mutex_unlock(&data->lock);
+
+ /* Distance (mm) = ((BYTE_H << 16) + (BYTE_M << 8) + BYTE_L)/1000 */
+ distance_mm = ((raw[0] << 16) + (raw[1] << 8) + raw[2])/1000;
+
+ return distance_mm;
+}
+
+static int rcwl96xx_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *channel,
+ int *val,
+ int *val2,
+ long info)
+{
+ struct rcwl96xx_data *data = iio_priv(indio_dev);
+ int ret;
+
+ if (channel->type != IIO_DISTANCE)
+ return -EINVAL;
+
+ switch (info) {
+ case IIO_CHAN_INFO_RAW:
+ ret = rcwl96xx_read(data);
+ *val = ret;
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ *val = 0;
+ *val2 = 1000;
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct iio_info rcwl96xx_info = {
+ .read_raw = rcwl96xx_read_raw,
+};
+
+static const struct iio_chan_spec rcwl96xx_chan_spec[] = {
+ {
+ .type = IIO_DISTANCE,
+ .info_mask_separate =
+ BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ },
+};
+
+static int rcwl96xx_probe(struct i2c_client *client)
+{
+ struct rcwl96xx_data *data;
+ struct iio_dev *indio_dev;
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ data = iio_priv(indio_dev);
+ i2c_set_clientdata(client, indio_dev);
+ data->client = client;
+
+ mutex_init(&data->lock);
+
+ indio_dev->info = &rcwl96xx_info;
+ indio_dev->channels = rcwl96xx_chan_spec;
+ indio_dev->num_channels = ARRAY_SIZE(rcwl96xx_chan_spec);
+ indio_dev->name = "rcwl96xx";
+ indio_dev->modes = INDIO_DIRECT_MODE;
+
+ return devm_iio_device_register(&client->dev, indio_dev);
+}
+
+static const struct of_device_id rcwl96xx_of_match[] = {
+ {
+ .compatible = "mangze,rcwl96xx",
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, rcwl96xx_of_match);
+
+static struct i2c_driver rcwl96xx_driver = {
+ .driver = {
+ .name = "rcwl96xx",
+ .of_match_table = rcwl96xx_of_match,
+ },
+ .probe = rcwl96xx_probe,
+};
+module_i2c_driver(rcwl96xx_driver);
+
+MODULE_AUTHOR("William Goodspeed <goodspeed@mailo.cat>");
+MODULE_DESCRIPTION("Mangze RCWL96XX ultrasonic distance sensor driver");
+MODULE_LICENSE("GPL");
|