18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * pulsedlight-lidar-lite-v2.c - Support for PulsedLight LIDAR sensor 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2015, 2017-2018 68c2ecf20Sopenharmony_ci * Author: Matt Ranostay <matt.ranostay@konsulko.com> 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * TODO: interrupt mode, and signal strength reporting 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/err.h> 128c2ecf20Sopenharmony_ci#include <linux/init.h> 138c2ecf20Sopenharmony_ci#include <linux/i2c.h> 148c2ecf20Sopenharmony_ci#include <linux/delay.h> 158c2ecf20Sopenharmony_ci#include <linux/module.h> 168c2ecf20Sopenharmony_ci#include <linux/mod_devicetable.h> 178c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h> 188c2ecf20Sopenharmony_ci#include <linux/iio/iio.h> 198c2ecf20Sopenharmony_ci#include <linux/iio/sysfs.h> 208c2ecf20Sopenharmony_ci#include <linux/iio/buffer.h> 218c2ecf20Sopenharmony_ci#include <linux/iio/trigger.h> 228c2ecf20Sopenharmony_ci#include <linux/iio/triggered_buffer.h> 238c2ecf20Sopenharmony_ci#include <linux/iio/trigger_consumer.h> 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#define LIDAR_REG_CONTROL 0x00 268c2ecf20Sopenharmony_ci#define LIDAR_REG_CONTROL_ACQUIRE BIT(2) 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#define LIDAR_REG_STATUS 0x01 298c2ecf20Sopenharmony_ci#define LIDAR_REG_STATUS_INVALID BIT(3) 308c2ecf20Sopenharmony_ci#define LIDAR_REG_STATUS_READY BIT(0) 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#define LIDAR_REG_DATA_HBYTE 0x0f 338c2ecf20Sopenharmony_ci#define LIDAR_REG_DATA_LBYTE 0x10 348c2ecf20Sopenharmony_ci#define LIDAR_REG_DATA_WORD_READ BIT(7) 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#define LIDAR_REG_PWR_CONTROL 0x65 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#define LIDAR_DRV_NAME "lidar" 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_cistruct lidar_data { 418c2ecf20Sopenharmony_ci struct iio_dev *indio_dev; 428c2ecf20Sopenharmony_ci struct i2c_client *client; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci int (*xfer)(struct lidar_data *data, u8 reg, u8 *val, int len); 458c2ecf20Sopenharmony_ci int i2c_enabled; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci /* Ensure timestamp is naturally aligned */ 488c2ecf20Sopenharmony_ci struct { 498c2ecf20Sopenharmony_ci u16 chan; 508c2ecf20Sopenharmony_ci s64 timestamp __aligned(8); 518c2ecf20Sopenharmony_ci } scan; 528c2ecf20Sopenharmony_ci}; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_cistatic const struct iio_chan_spec lidar_channels[] = { 558c2ecf20Sopenharmony_ci { 568c2ecf20Sopenharmony_ci .type = IIO_DISTANCE, 578c2ecf20Sopenharmony_ci .info_mask_separate = 588c2ecf20Sopenharmony_ci BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), 598c2ecf20Sopenharmony_ci .scan_index = 0, 608c2ecf20Sopenharmony_ci .scan_type = { 618c2ecf20Sopenharmony_ci .sign = 'u', 628c2ecf20Sopenharmony_ci .realbits = 16, 638c2ecf20Sopenharmony_ci .storagebits = 16, 648c2ecf20Sopenharmony_ci }, 658c2ecf20Sopenharmony_ci }, 668c2ecf20Sopenharmony_ci IIO_CHAN_SOFT_TIMESTAMP(1), 678c2ecf20Sopenharmony_ci}; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_cistatic int lidar_i2c_xfer(struct lidar_data *data, u8 reg, u8 *val, int len) 708c2ecf20Sopenharmony_ci{ 718c2ecf20Sopenharmony_ci struct i2c_client *client = data->client; 728c2ecf20Sopenharmony_ci struct i2c_msg msg[2]; 738c2ecf20Sopenharmony_ci int ret; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci msg[0].addr = client->addr; 768c2ecf20Sopenharmony_ci msg[0].flags = client->flags | I2C_M_STOP; 778c2ecf20Sopenharmony_ci msg[0].len = 1; 788c2ecf20Sopenharmony_ci msg[0].buf = (char *) ® 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci msg[1].addr = client->addr; 818c2ecf20Sopenharmony_ci msg[1].flags = client->flags | I2C_M_RD; 828c2ecf20Sopenharmony_ci msg[1].len = len; 838c2ecf20Sopenharmony_ci msg[1].buf = (char *) val; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci ret = i2c_transfer(client->adapter, msg, 2); 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci return (ret == 2) ? 0 : -EIO; 888c2ecf20Sopenharmony_ci} 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cistatic int lidar_smbus_xfer(struct lidar_data *data, u8 reg, u8 *val, int len) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci struct i2c_client *client = data->client; 938c2ecf20Sopenharmony_ci int ret; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci /* 968c2ecf20Sopenharmony_ci * Device needs a STOP condition between address write, and data read 978c2ecf20Sopenharmony_ci * so in turn i2c_smbus_read_byte_data cannot be used 988c2ecf20Sopenharmony_ci */ 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci while (len--) { 1018c2ecf20Sopenharmony_ci ret = i2c_smbus_write_byte(client, reg++); 1028c2ecf20Sopenharmony_ci if (ret < 0) { 1038c2ecf20Sopenharmony_ci dev_err(&client->dev, "cannot write addr value"); 1048c2ecf20Sopenharmony_ci return ret; 1058c2ecf20Sopenharmony_ci } 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci ret = i2c_smbus_read_byte(client); 1088c2ecf20Sopenharmony_ci if (ret < 0) { 1098c2ecf20Sopenharmony_ci dev_err(&client->dev, "cannot read data value"); 1108c2ecf20Sopenharmony_ci return ret; 1118c2ecf20Sopenharmony_ci } 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci *(val++) = ret; 1148c2ecf20Sopenharmony_ci } 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci return 0; 1178c2ecf20Sopenharmony_ci} 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_cistatic int lidar_read_byte(struct lidar_data *data, u8 reg) 1208c2ecf20Sopenharmony_ci{ 1218c2ecf20Sopenharmony_ci int ret; 1228c2ecf20Sopenharmony_ci u8 val; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci ret = data->xfer(data, reg, &val, 1); 1258c2ecf20Sopenharmony_ci if (ret < 0) 1268c2ecf20Sopenharmony_ci return ret; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci return val; 1298c2ecf20Sopenharmony_ci} 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_cistatic inline int lidar_write_control(struct lidar_data *data, int val) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci return i2c_smbus_write_byte_data(data->client, LIDAR_REG_CONTROL, val); 1348c2ecf20Sopenharmony_ci} 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_cistatic inline int lidar_write_power(struct lidar_data *data, int val) 1378c2ecf20Sopenharmony_ci{ 1388c2ecf20Sopenharmony_ci return i2c_smbus_write_byte_data(data->client, 1398c2ecf20Sopenharmony_ci LIDAR_REG_PWR_CONTROL, val); 1408c2ecf20Sopenharmony_ci} 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_cistatic int lidar_read_measurement(struct lidar_data *data, u16 *reg) 1438c2ecf20Sopenharmony_ci{ 1448c2ecf20Sopenharmony_ci __be16 value; 1458c2ecf20Sopenharmony_ci int ret = data->xfer(data, LIDAR_REG_DATA_HBYTE | 1468c2ecf20Sopenharmony_ci (data->i2c_enabled ? LIDAR_REG_DATA_WORD_READ : 0), 1478c2ecf20Sopenharmony_ci (u8 *) &value, 2); 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci if (!ret) 1508c2ecf20Sopenharmony_ci *reg = be16_to_cpu(value); 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci return ret; 1538c2ecf20Sopenharmony_ci} 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_cistatic int lidar_get_measurement(struct lidar_data *data, u16 *reg) 1568c2ecf20Sopenharmony_ci{ 1578c2ecf20Sopenharmony_ci struct i2c_client *client = data->client; 1588c2ecf20Sopenharmony_ci int tries = 10; 1598c2ecf20Sopenharmony_ci int ret; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci pm_runtime_get_sync(&client->dev); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci /* start sample */ 1648c2ecf20Sopenharmony_ci ret = lidar_write_control(data, LIDAR_REG_CONTROL_ACQUIRE); 1658c2ecf20Sopenharmony_ci if (ret < 0) { 1668c2ecf20Sopenharmony_ci dev_err(&client->dev, "cannot send start measurement command"); 1678c2ecf20Sopenharmony_ci pm_runtime_put_noidle(&client->dev); 1688c2ecf20Sopenharmony_ci return ret; 1698c2ecf20Sopenharmony_ci } 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci while (tries--) { 1728c2ecf20Sopenharmony_ci usleep_range(1000, 2000); 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci ret = lidar_read_byte(data, LIDAR_REG_STATUS); 1758c2ecf20Sopenharmony_ci if (ret < 0) 1768c2ecf20Sopenharmony_ci break; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci /* return -EINVAL since laser is likely pointed out of range */ 1798c2ecf20Sopenharmony_ci if (ret & LIDAR_REG_STATUS_INVALID) { 1808c2ecf20Sopenharmony_ci *reg = 0; 1818c2ecf20Sopenharmony_ci ret = -EINVAL; 1828c2ecf20Sopenharmony_ci break; 1838c2ecf20Sopenharmony_ci } 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci /* sample ready to read */ 1868c2ecf20Sopenharmony_ci if (!(ret & LIDAR_REG_STATUS_READY)) { 1878c2ecf20Sopenharmony_ci ret = lidar_read_measurement(data, reg); 1888c2ecf20Sopenharmony_ci break; 1898c2ecf20Sopenharmony_ci } 1908c2ecf20Sopenharmony_ci ret = -EIO; 1918c2ecf20Sopenharmony_ci } 1928c2ecf20Sopenharmony_ci pm_runtime_mark_last_busy(&client->dev); 1938c2ecf20Sopenharmony_ci pm_runtime_put_autosuspend(&client->dev); 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci return ret; 1968c2ecf20Sopenharmony_ci} 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_cistatic int lidar_read_raw(struct iio_dev *indio_dev, 1998c2ecf20Sopenharmony_ci struct iio_chan_spec const *chan, 2008c2ecf20Sopenharmony_ci int *val, int *val2, long mask) 2018c2ecf20Sopenharmony_ci{ 2028c2ecf20Sopenharmony_ci struct lidar_data *data = iio_priv(indio_dev); 2038c2ecf20Sopenharmony_ci int ret = -EINVAL; 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci switch (mask) { 2068c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_RAW: { 2078c2ecf20Sopenharmony_ci u16 reg; 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci if (iio_device_claim_direct_mode(indio_dev)) 2108c2ecf20Sopenharmony_ci return -EBUSY; 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci ret = lidar_get_measurement(data, ®); 2138c2ecf20Sopenharmony_ci if (!ret) { 2148c2ecf20Sopenharmony_ci *val = reg; 2158c2ecf20Sopenharmony_ci ret = IIO_VAL_INT; 2168c2ecf20Sopenharmony_ci } 2178c2ecf20Sopenharmony_ci iio_device_release_direct_mode(indio_dev); 2188c2ecf20Sopenharmony_ci break; 2198c2ecf20Sopenharmony_ci } 2208c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_SCALE: 2218c2ecf20Sopenharmony_ci *val = 0; 2228c2ecf20Sopenharmony_ci *val2 = 10000; 2238c2ecf20Sopenharmony_ci ret = IIO_VAL_INT_PLUS_MICRO; 2248c2ecf20Sopenharmony_ci break; 2258c2ecf20Sopenharmony_ci } 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci return ret; 2288c2ecf20Sopenharmony_ci} 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_cistatic irqreturn_t lidar_trigger_handler(int irq, void *private) 2318c2ecf20Sopenharmony_ci{ 2328c2ecf20Sopenharmony_ci struct iio_poll_func *pf = private; 2338c2ecf20Sopenharmony_ci struct iio_dev *indio_dev = pf->indio_dev; 2348c2ecf20Sopenharmony_ci struct lidar_data *data = iio_priv(indio_dev); 2358c2ecf20Sopenharmony_ci int ret; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci ret = lidar_get_measurement(data, &data->scan.chan); 2388c2ecf20Sopenharmony_ci if (!ret) { 2398c2ecf20Sopenharmony_ci iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, 2408c2ecf20Sopenharmony_ci iio_get_time_ns(indio_dev)); 2418c2ecf20Sopenharmony_ci } else if (ret != -EINVAL) { 2428c2ecf20Sopenharmony_ci dev_err(&data->client->dev, "cannot read LIDAR measurement"); 2438c2ecf20Sopenharmony_ci } 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci iio_trigger_notify_done(indio_dev->trig); 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci return IRQ_HANDLED; 2488c2ecf20Sopenharmony_ci} 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_cistatic const struct iio_info lidar_info = { 2518c2ecf20Sopenharmony_ci .read_raw = lidar_read_raw, 2528c2ecf20Sopenharmony_ci}; 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_cistatic int lidar_probe(struct i2c_client *client, 2558c2ecf20Sopenharmony_ci const struct i2c_device_id *id) 2568c2ecf20Sopenharmony_ci{ 2578c2ecf20Sopenharmony_ci struct lidar_data *data; 2588c2ecf20Sopenharmony_ci struct iio_dev *indio_dev; 2598c2ecf20Sopenharmony_ci int ret; 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 2628c2ecf20Sopenharmony_ci if (!indio_dev) 2638c2ecf20Sopenharmony_ci return -ENOMEM; 2648c2ecf20Sopenharmony_ci data = iio_priv(indio_dev); 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 2678c2ecf20Sopenharmony_ci data->xfer = lidar_i2c_xfer; 2688c2ecf20Sopenharmony_ci data->i2c_enabled = 1; 2698c2ecf20Sopenharmony_ci } else if (i2c_check_functionality(client->adapter, 2708c2ecf20Sopenharmony_ci I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BYTE)) 2718c2ecf20Sopenharmony_ci data->xfer = lidar_smbus_xfer; 2728c2ecf20Sopenharmony_ci else 2738c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci indio_dev->info = &lidar_info; 2768c2ecf20Sopenharmony_ci indio_dev->name = LIDAR_DRV_NAME; 2778c2ecf20Sopenharmony_ci indio_dev->channels = lidar_channels; 2788c2ecf20Sopenharmony_ci indio_dev->num_channels = ARRAY_SIZE(lidar_channels); 2798c2ecf20Sopenharmony_ci indio_dev->modes = INDIO_DIRECT_MODE; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci i2c_set_clientdata(client, indio_dev); 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci data->client = client; 2848c2ecf20Sopenharmony_ci data->indio_dev = indio_dev; 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci ret = iio_triggered_buffer_setup(indio_dev, NULL, 2878c2ecf20Sopenharmony_ci lidar_trigger_handler, NULL); 2888c2ecf20Sopenharmony_ci if (ret) 2898c2ecf20Sopenharmony_ci return ret; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci ret = iio_device_register(indio_dev); 2928c2ecf20Sopenharmony_ci if (ret) 2938c2ecf20Sopenharmony_ci goto error_unreg_buffer; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci pm_runtime_set_autosuspend_delay(&client->dev, 1000); 2968c2ecf20Sopenharmony_ci pm_runtime_use_autosuspend(&client->dev); 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci ret = pm_runtime_set_active(&client->dev); 2998c2ecf20Sopenharmony_ci if (ret) 3008c2ecf20Sopenharmony_ci goto error_unreg_buffer; 3018c2ecf20Sopenharmony_ci pm_runtime_enable(&client->dev); 3028c2ecf20Sopenharmony_ci pm_runtime_idle(&client->dev); 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci return 0; 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_cierror_unreg_buffer: 3078c2ecf20Sopenharmony_ci iio_triggered_buffer_cleanup(indio_dev); 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci return ret; 3108c2ecf20Sopenharmony_ci} 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_cistatic int lidar_remove(struct i2c_client *client) 3138c2ecf20Sopenharmony_ci{ 3148c2ecf20Sopenharmony_ci struct iio_dev *indio_dev = i2c_get_clientdata(client); 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci iio_device_unregister(indio_dev); 3178c2ecf20Sopenharmony_ci iio_triggered_buffer_cleanup(indio_dev); 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci pm_runtime_disable(&client->dev); 3208c2ecf20Sopenharmony_ci pm_runtime_set_suspended(&client->dev); 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci return 0; 3238c2ecf20Sopenharmony_ci} 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_cistatic const struct i2c_device_id lidar_id[] = { 3268c2ecf20Sopenharmony_ci {"lidar-lite-v2", 0}, 3278c2ecf20Sopenharmony_ci {"lidar-lite-v3", 0}, 3288c2ecf20Sopenharmony_ci { }, 3298c2ecf20Sopenharmony_ci}; 3308c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, lidar_id); 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_cistatic const struct of_device_id lidar_dt_ids[] = { 3338c2ecf20Sopenharmony_ci { .compatible = "pulsedlight,lidar-lite-v2" }, 3348c2ecf20Sopenharmony_ci { .compatible = "grmn,lidar-lite-v3" }, 3358c2ecf20Sopenharmony_ci { } 3368c2ecf20Sopenharmony_ci}; 3378c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, lidar_dt_ids); 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 3408c2ecf20Sopenharmony_cistatic int lidar_pm_runtime_suspend(struct device *dev) 3418c2ecf20Sopenharmony_ci{ 3428c2ecf20Sopenharmony_ci struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 3438c2ecf20Sopenharmony_ci struct lidar_data *data = iio_priv(indio_dev); 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci return lidar_write_power(data, 0x0f); 3468c2ecf20Sopenharmony_ci} 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_cistatic int lidar_pm_runtime_resume(struct device *dev) 3498c2ecf20Sopenharmony_ci{ 3508c2ecf20Sopenharmony_ci struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 3518c2ecf20Sopenharmony_ci struct lidar_data *data = iio_priv(indio_dev); 3528c2ecf20Sopenharmony_ci int ret = lidar_write_power(data, 0); 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci /* regulator and FPGA needs settling time */ 3558c2ecf20Sopenharmony_ci usleep_range(15000, 20000); 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci return ret; 3588c2ecf20Sopenharmony_ci} 3598c2ecf20Sopenharmony_ci#endif 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_cistatic const struct dev_pm_ops lidar_pm_ops = { 3628c2ecf20Sopenharmony_ci SET_RUNTIME_PM_OPS(lidar_pm_runtime_suspend, 3638c2ecf20Sopenharmony_ci lidar_pm_runtime_resume, NULL) 3648c2ecf20Sopenharmony_ci}; 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_cistatic struct i2c_driver lidar_driver = { 3678c2ecf20Sopenharmony_ci .driver = { 3688c2ecf20Sopenharmony_ci .name = LIDAR_DRV_NAME, 3698c2ecf20Sopenharmony_ci .of_match_table = lidar_dt_ids, 3708c2ecf20Sopenharmony_ci .pm = &lidar_pm_ops, 3718c2ecf20Sopenharmony_ci }, 3728c2ecf20Sopenharmony_ci .probe = lidar_probe, 3738c2ecf20Sopenharmony_ci .remove = lidar_remove, 3748c2ecf20Sopenharmony_ci .id_table = lidar_id, 3758c2ecf20Sopenharmony_ci}; 3768c2ecf20Sopenharmony_cimodule_i2c_driver(lidar_driver); 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ciMODULE_AUTHOR("Matt Ranostay <matt.ranostay@konsulko.com>"); 3798c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("PulsedLight LIDAR sensor"); 3808c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 381