diff options
Diffstat (limited to 'drivers/iio/proximity')
-rw-r--r-- | drivers/iio/proximity/pulsedlight-lidar-lite-v2.c | 56 |
1 files changed, 55 insertions, 1 deletions
diff --git a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c index 961f9f990faf..be8ccef735f8 100644 --- a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c +++ b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c | |||
@@ -13,7 +13,7 @@ | |||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | * GNU General Public License for more details. | 14 | * GNU General Public License for more details. |
15 | * | 15 | * |
16 | * TODO: runtime pm, interrupt mode, and signal strength reporting | 16 | * TODO: interrupt mode, and signal strength reporting |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/err.h> | 19 | #include <linux/err.h> |
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/i2c.h> | 21 | #include <linux/i2c.h> |
22 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/pm_runtime.h> | ||
24 | #include <linux/iio/iio.h> | 25 | #include <linux/iio/iio.h> |
25 | #include <linux/iio/sysfs.h> | 26 | #include <linux/iio/sysfs.h> |
26 | #include <linux/iio/buffer.h> | 27 | #include <linux/iio/buffer.h> |
@@ -37,6 +38,7 @@ | |||
37 | 38 | ||
38 | #define LIDAR_REG_DATA_HBYTE 0x0f | 39 | #define LIDAR_REG_DATA_HBYTE 0x0f |
39 | #define LIDAR_REG_DATA_LBYTE 0x10 | 40 | #define LIDAR_REG_DATA_LBYTE 0x10 |
41 | #define LIDAR_REG_PWR_CONTROL 0x65 | ||
40 | 42 | ||
41 | #define LIDAR_DRV_NAME "lidar" | 43 | #define LIDAR_DRV_NAME "lidar" |
42 | 44 | ||
@@ -90,6 +92,12 @@ static inline int lidar_write_control(struct lidar_data *data, int val) | |||
90 | return i2c_smbus_write_byte_data(data->client, LIDAR_REG_CONTROL, val); | 92 | return i2c_smbus_write_byte_data(data->client, LIDAR_REG_CONTROL, val); |
91 | } | 93 | } |
92 | 94 | ||
95 | static inline int lidar_write_power(struct lidar_data *data, int val) | ||
96 | { | ||
97 | return i2c_smbus_write_byte_data(data->client, | ||
98 | LIDAR_REG_PWR_CONTROL, val); | ||
99 | } | ||
100 | |||
93 | static int lidar_read_measurement(struct lidar_data *data, u16 *reg) | 101 | static int lidar_read_measurement(struct lidar_data *data, u16 *reg) |
94 | { | 102 | { |
95 | int ret; | 103 | int ret; |
@@ -116,6 +124,8 @@ static int lidar_get_measurement(struct lidar_data *data, u16 *reg) | |||
116 | int tries = 10; | 124 | int tries = 10; |
117 | int ret; | 125 | int ret; |
118 | 126 | ||
127 | pm_runtime_get_sync(&client->dev); | ||
128 | |||
119 | /* start sample */ | 129 | /* start sample */ |
120 | ret = lidar_write_control(data, LIDAR_REG_CONTROL_ACQUIRE); | 130 | ret = lidar_write_control(data, LIDAR_REG_CONTROL_ACQUIRE); |
121 | if (ret < 0) { | 131 | if (ret < 0) { |
@@ -144,6 +154,8 @@ static int lidar_get_measurement(struct lidar_data *data, u16 *reg) | |||
144 | } | 154 | } |
145 | ret = -EIO; | 155 | ret = -EIO; |
146 | } | 156 | } |
157 | pm_runtime_mark_last_busy(&client->dev); | ||
158 | pm_runtime_put_autosuspend(&client->dev); | ||
147 | 159 | ||
148 | return ret; | 160 | return ret; |
149 | } | 161 | } |
@@ -243,6 +255,17 @@ static int lidar_probe(struct i2c_client *client, | |||
243 | if (ret) | 255 | if (ret) |
244 | goto error_unreg_buffer; | 256 | goto error_unreg_buffer; |
245 | 257 | ||
258 | pm_runtime_set_autosuspend_delay(&client->dev, 1000); | ||
259 | pm_runtime_use_autosuspend(&client->dev); | ||
260 | |||
261 | ret = pm_runtime_set_active(&client->dev); | ||
262 | if (ret) | ||
263 | goto error_unreg_buffer; | ||
264 | pm_runtime_enable(&client->dev); | ||
265 | |||
266 | pm_runtime_mark_last_busy(&client->dev); | ||
267 | pm_runtime_idle(&client->dev); | ||
268 | |||
246 | return 0; | 269 | return 0; |
247 | 270 | ||
248 | error_unreg_buffer: | 271 | error_unreg_buffer: |
@@ -258,6 +281,9 @@ static int lidar_remove(struct i2c_client *client) | |||
258 | iio_device_unregister(indio_dev); | 281 | iio_device_unregister(indio_dev); |
259 | iio_triggered_buffer_cleanup(indio_dev); | 282 | iio_triggered_buffer_cleanup(indio_dev); |
260 | 283 | ||
284 | pm_runtime_disable(&client->dev); | ||
285 | pm_runtime_set_suspended(&client->dev); | ||
286 | |||
261 | return 0; | 287 | return 0; |
262 | } | 288 | } |
263 | 289 | ||
@@ -273,10 +299,38 @@ static const struct of_device_id lidar_dt_ids[] = { | |||
273 | }; | 299 | }; |
274 | MODULE_DEVICE_TABLE(of, lidar_dt_ids); | 300 | MODULE_DEVICE_TABLE(of, lidar_dt_ids); |
275 | 301 | ||
302 | #ifdef CONFIG_PM | ||
303 | static int lidar_pm_runtime_suspend(struct device *dev) | ||
304 | { | ||
305 | struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); | ||
306 | struct lidar_data *data = iio_priv(indio_dev); | ||
307 | |||
308 | return lidar_write_power(data, 0x0f); | ||
309 | } | ||
310 | |||
311 | static int lidar_pm_runtime_resume(struct device *dev) | ||
312 | { | ||
313 | struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); | ||
314 | struct lidar_data *data = iio_priv(indio_dev); | ||
315 | int ret = lidar_write_power(data, 0); | ||
316 | |||
317 | /* regulator and FPGA needs settling time */ | ||
318 | usleep_range(15000, 20000); | ||
319 | |||
320 | return ret; | ||
321 | } | ||
322 | #endif | ||
323 | |||
324 | static const struct dev_pm_ops lidar_pm_ops = { | ||
325 | SET_RUNTIME_PM_OPS(lidar_pm_runtime_suspend, | ||
326 | lidar_pm_runtime_resume, NULL) | ||
327 | }; | ||
328 | |||
276 | static struct i2c_driver lidar_driver = { | 329 | static struct i2c_driver lidar_driver = { |
277 | .driver = { | 330 | .driver = { |
278 | .name = LIDAR_DRV_NAME, | 331 | .name = LIDAR_DRV_NAME, |
279 | .of_match_table = of_match_ptr(lidar_dt_ids), | 332 | .of_match_table = of_match_ptr(lidar_dt_ids), |
333 | .pm = &lidar_pm_ops, | ||
280 | }, | 334 | }, |
281 | .probe = lidar_probe, | 335 | .probe = lidar_probe, |
282 | .remove = lidar_remove, | 336 | .remove = lidar_remove, |