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