1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * pulsedlight-lidar-lite-v2.c - Support for PulsedLight LIDAR sensor
4 *
5 * Copyright (C) 2015, 2017-2018
6 * Author: Matt Ranostay <matt.ranostay@konsulko.com>
7 *
8 * TODO: interrupt mode, and signal strength reporting
9 */
10
11 #include <linux/err.h>
12 #include <linux/init.h>
13 #include <linux/i2c.h>
14 #include <linux/delay.h>
15 #include <linux/module.h>
16 #include <linux/mod_devicetable.h>
17 #include <linux/pm_runtime.h>
18 #include <linux/iio/iio.h>
19 #include <linux/iio/sysfs.h>
20 #include <linux/iio/buffer.h>
21 #include <linux/iio/trigger.h>
22 #include <linux/iio/triggered_buffer.h>
23 #include <linux/iio/trigger_consumer.h>
24
25 #define LIDAR_REG_CONTROL 0x00
26 #define LIDAR_REG_CONTROL_ACQUIRE BIT(2)
27
28 #define LIDAR_REG_STATUS 0x01
29 #define LIDAR_REG_STATUS_INVALID BIT(3)
30 #define LIDAR_REG_STATUS_READY BIT(0)
31
32 #define LIDAR_REG_DATA_HBYTE 0x0f
33 #define LIDAR_REG_DATA_LBYTE 0x10
34 #define LIDAR_REG_DATA_WORD_READ BIT(7)
35
36 #define LIDAR_REG_PWR_CONTROL 0x65
37
38 #define LIDAR_DRV_NAME "lidar"
39
40 struct lidar_data {
41 struct iio_dev *indio_dev;
42 struct i2c_client *client;
43
44 int (*xfer)(struct lidar_data *data, u8 reg, u8 *val, int len);
45 int i2c_enabled;
46 };
47
48 static const struct iio_chan_spec lidar_channels[] = {
49 {
50 .type = IIO_DISTANCE,
51 .info_mask_separate =
52 BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
53 .scan_index = 0,
54 .scan_type = {
55 .sign = 'u',
56 .realbits = 16,
57 .storagebits = 16,
58 },
59 },
60 IIO_CHAN_SOFT_TIMESTAMP(1),
61 };
62
lidar_i2c_xfer(struct lidar_data * data,u8 reg,u8 * val,int len)63 static int lidar_i2c_xfer(struct lidar_data *data, u8 reg, u8 *val, int len)
64 {
65 struct i2c_client *client = data->client;
66 struct i2c_msg msg[2];
67 int ret;
68
69 msg[0].addr = client->addr;
70 msg[0].flags = client->flags | I2C_M_STOP;
71 msg[0].len = 1;
72 msg[0].buf = (char *) ®
73
74 msg[1].addr = client->addr;
75 msg[1].flags = client->flags | I2C_M_RD;
76 msg[1].len = len;
77 msg[1].buf = (char *) val;
78
79 ret = i2c_transfer(client->adapter, msg, 2);
80
81 return (ret == 2) ? 0 : -EIO;
82 }
83
lidar_smbus_xfer(struct lidar_data * data,u8 reg,u8 * val,int len)84 static int lidar_smbus_xfer(struct lidar_data *data, u8 reg, u8 *val, int len)
85 {
86 struct i2c_client *client = data->client;
87 int ret;
88
89 /*
90 * Device needs a STOP condition between address write, and data read
91 * so in turn i2c_smbus_read_byte_data cannot be used
92 */
93
94 while (len--) {
95 ret = i2c_smbus_write_byte(client, reg++);
96 if (ret < 0) {
97 dev_err(&client->dev, "cannot write addr value");
98 return ret;
99 }
100
101 ret = i2c_smbus_read_byte(client);
102 if (ret < 0) {
103 dev_err(&client->dev, "cannot read data value");
104 return ret;
105 }
106
107 *(val++) = ret;
108 }
109
110 return 0;
111 }
112
lidar_read_byte(struct lidar_data * data,u8 reg)113 static int lidar_read_byte(struct lidar_data *data, u8 reg)
114 {
115 int ret;
116 u8 val;
117
118 ret = data->xfer(data, reg, &val, 1);
119 if (ret < 0)
120 return ret;
121
122 return val;
123 }
124
lidar_write_control(struct lidar_data * data,int val)125 static inline int lidar_write_control(struct lidar_data *data, int val)
126 {
127 return i2c_smbus_write_byte_data(data->client, LIDAR_REG_CONTROL, val);
128 }
129
lidar_write_power(struct lidar_data * data,int val)130 static inline int lidar_write_power(struct lidar_data *data, int val)
131 {
132 return i2c_smbus_write_byte_data(data->client,
133 LIDAR_REG_PWR_CONTROL, val);
134 }
135
lidar_read_measurement(struct lidar_data * data,u16 * reg)136 static int lidar_read_measurement(struct lidar_data *data, u16 *reg)
137 {
138 __be16 value;
139 int ret = data->xfer(data, LIDAR_REG_DATA_HBYTE |
140 (data->i2c_enabled ? LIDAR_REG_DATA_WORD_READ : 0),
141 (u8 *) &value, 2);
142
143 if (!ret)
144 *reg = be16_to_cpu(value);
145
146 return ret;
147 }
148
lidar_get_measurement(struct lidar_data * data,u16 * reg)149 static int lidar_get_measurement(struct lidar_data *data, u16 *reg)
150 {
151 struct i2c_client *client = data->client;
152 int tries = 10;
153 int ret;
154
155 ret = pm_runtime_resume_and_get(&client->dev);
156 if (ret < 0)
157 return ret;
158
159 /* start sample */
160 ret = lidar_write_control(data, LIDAR_REG_CONTROL_ACQUIRE);
161 if (ret < 0) {
162 dev_err(&client->dev, "cannot send start measurement command");
163 pm_runtime_put_noidle(&client->dev);
164 return ret;
165 }
166
167 while (tries--) {
168 usleep_range(1000, 2000);
169
170 ret = lidar_read_byte(data, LIDAR_REG_STATUS);
171 if (ret < 0)
172 break;
173
174 /* return -EINVAL since laser is likely pointed out of range */
175 if (ret & LIDAR_REG_STATUS_INVALID) {
176 *reg = 0;
177 ret = -EINVAL;
178 break;
179 }
180
181 /* sample ready to read */
182 if (!(ret & LIDAR_REG_STATUS_READY)) {
183 ret = lidar_read_measurement(data, reg);
184 break;
185 }
186 ret = -EIO;
187 }
188 pm_runtime_put_autosuspend(&client->dev);
189
190 return ret;
191 }
192
lidar_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)193 static int lidar_read_raw(struct iio_dev *indio_dev,
194 struct iio_chan_spec const *chan,
195 int *val, int *val2, long mask)
196 {
197 struct lidar_data *data = iio_priv(indio_dev);
198 int ret = -EINVAL;
199
200 switch (mask) {
201 case IIO_CHAN_INFO_RAW: {
202 u16 reg;
203
204 if (!iio_device_claim_direct(indio_dev))
205 return -EBUSY;
206
207 ret = lidar_get_measurement(data, ®);
208 if (!ret) {
209 *val = reg;
210 ret = IIO_VAL_INT;
211 }
212 iio_device_release_direct(indio_dev);
213 break;
214 }
215 case IIO_CHAN_INFO_SCALE:
216 *val = 0;
217 *val2 = 10000;
218 ret = IIO_VAL_INT_PLUS_MICRO;
219 break;
220 }
221
222 return ret;
223 }
224
lidar_trigger_handler(int irq,void * private)225 static irqreturn_t lidar_trigger_handler(int irq, void *private)
226 {
227 struct iio_poll_func *pf = private;
228 struct iio_dev *indio_dev = pf->indio_dev;
229 struct lidar_data *data = iio_priv(indio_dev);
230 int ret;
231 struct {
232 u16 chan;
233 aligned_s64 timestamp;
234 } scan = { };
235
236 ret = lidar_get_measurement(data, &scan.chan);
237 if (!ret) {
238 iio_push_to_buffers_with_ts(indio_dev, &scan, sizeof(scan),
239 iio_get_time_ns(indio_dev));
240 } else if (ret != -EINVAL) {
241 dev_err(&data->client->dev, "cannot read LIDAR measurement");
242 }
243
244 iio_trigger_notify_done(indio_dev->trig);
245
246 return IRQ_HANDLED;
247 }
248
249 static const struct iio_info lidar_info = {
250 .read_raw = lidar_read_raw,
251 };
252
lidar_probe(struct i2c_client * client)253 static int lidar_probe(struct i2c_client *client)
254 {
255 struct lidar_data *data;
256 struct iio_dev *indio_dev;
257 int ret;
258
259 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
260 if (!indio_dev)
261 return -ENOMEM;
262 data = iio_priv(indio_dev);
263
264 if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
265 data->xfer = lidar_i2c_xfer;
266 data->i2c_enabled = 1;
267 } else if (i2c_check_functionality(client->adapter,
268 I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BYTE))
269 data->xfer = lidar_smbus_xfer;
270 else
271 return -EOPNOTSUPP;
272
273 indio_dev->info = &lidar_info;
274 indio_dev->name = LIDAR_DRV_NAME;
275 indio_dev->channels = lidar_channels;
276 indio_dev->num_channels = ARRAY_SIZE(lidar_channels);
277 indio_dev->modes = INDIO_DIRECT_MODE;
278
279 i2c_set_clientdata(client, indio_dev);
280
281 data->client = client;
282 data->indio_dev = indio_dev;
283
284 ret = iio_triggered_buffer_setup(indio_dev, NULL,
285 lidar_trigger_handler, NULL);
286 if (ret)
287 return ret;
288
289 ret = iio_device_register(indio_dev);
290 if (ret)
291 goto error_unreg_buffer;
292
293 pm_runtime_set_autosuspend_delay(&client->dev, 1000);
294 pm_runtime_use_autosuspend(&client->dev);
295
296 ret = pm_runtime_set_active(&client->dev);
297 if (ret)
298 goto error_unreg_buffer;
299 pm_runtime_enable(&client->dev);
300 pm_runtime_idle(&client->dev);
301
302 return 0;
303
304 error_unreg_buffer:
305 iio_triggered_buffer_cleanup(indio_dev);
306
307 return ret;
308 }
309
lidar_remove(struct i2c_client * client)310 static void lidar_remove(struct i2c_client *client)
311 {
312 struct iio_dev *indio_dev = i2c_get_clientdata(client);
313
314 iio_device_unregister(indio_dev);
315 iio_triggered_buffer_cleanup(indio_dev);
316
317 pm_runtime_disable(&client->dev);
318 pm_runtime_set_suspended(&client->dev);
319 }
320
321 static const struct i2c_device_id lidar_id[] = {
322 { "lidar-lite-v2" },
323 { "lidar-lite-v3" },
324 { }
325 };
326 MODULE_DEVICE_TABLE(i2c, lidar_id);
327
328 static const struct of_device_id lidar_dt_ids[] = {
329 { .compatible = "pulsedlight,lidar-lite-v2" },
330 { .compatible = "grmn,lidar-lite-v3" },
331 { }
332 };
333 MODULE_DEVICE_TABLE(of, lidar_dt_ids);
334
lidar_pm_runtime_suspend(struct device * dev)335 static int lidar_pm_runtime_suspend(struct device *dev)
336 {
337 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
338 struct lidar_data *data = iio_priv(indio_dev);
339
340 return lidar_write_power(data, 0x0f);
341 }
342
lidar_pm_runtime_resume(struct device * dev)343 static int lidar_pm_runtime_resume(struct device *dev)
344 {
345 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
346 struct lidar_data *data = iio_priv(indio_dev);
347 int ret = lidar_write_power(data, 0);
348
349 /* regulator and FPGA needs settling time */
350 usleep_range(15000, 20000);
351
352 return ret;
353 }
354
355 static const struct dev_pm_ops lidar_pm_ops = {
356 RUNTIME_PM_OPS(lidar_pm_runtime_suspend, lidar_pm_runtime_resume, NULL)
357 };
358
359 static struct i2c_driver lidar_driver = {
360 .driver = {
361 .name = LIDAR_DRV_NAME,
362 .of_match_table = lidar_dt_ids,
363 .pm = pm_ptr(&lidar_pm_ops),
364 },
365 .probe = lidar_probe,
366 .remove = lidar_remove,
367 .id_table = lidar_id,
368 };
369 module_i2c_driver(lidar_driver);
370
371 MODULE_AUTHOR("Matt Ranostay <matt.ranostay@konsulko.com>");
372 MODULE_DESCRIPTION("PulsedLight LIDAR sensor");
373 MODULE_LICENSE("GPL");
374