aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdriana Reus <adriana.reus@intel.com>2015-11-24 05:59:51 -0500
committerJonathan Cameron <jic23@kernel.org>2015-12-02 13:42:05 -0500
commitf0e5f57d3ac25aa2afb25dc94d2b42a8defa8a19 (patch)
tree2ca5d7a0420330e9d02e3042fecdf270299652cb
parenta22a3c5c40deb31f03c2810a46e669bedbf476c5 (diff)
iio: light: us8152d: Add power management support
Add power management for sleep as well as runtime pm. Signed-off-by: Adriana Reus <adriana.reus@intel.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
-rw-r--r--drivers/iio/light/us5182d.c95
1 files changed, 88 insertions, 7 deletions
diff --git a/drivers/iio/light/us5182d.c b/drivers/iio/light/us5182d.c
index e67956c1f296..256c4bc12d21 100644
--- a/drivers/iio/light/us5182d.c
+++ b/drivers/iio/light/us5182d.c
@@ -23,6 +23,8 @@
23#include <linux/iio/iio.h> 23#include <linux/iio/iio.h>
24#include <linux/iio/sysfs.h> 24#include <linux/iio/sysfs.h>
25#include <linux/mutex.h> 25#include <linux/mutex.h>
26#include <linux/pm.h>
27#include <linux/pm_runtime.h>
26 28
27#define US5182D_REG_CFG0 0x00 29#define US5182D_REG_CFG0 0x00
28#define US5182D_CFG0_ONESHOT_EN BIT(6) 30#define US5182D_CFG0_ONESHOT_EN BIT(6)
@@ -81,6 +83,7 @@
81#define US5182D_READ_BYTE 1 83#define US5182D_READ_BYTE 1
82#define US5182D_READ_WORD 2 84#define US5182D_READ_WORD 2
83#define US5182D_OPSTORE_SLEEP_TIME 20 /* ms */ 85#define US5182D_OPSTORE_SLEEP_TIME 20 /* ms */
86#define US5182D_SLEEP_MS 3000 /* ms */
84 87
85/* Available ranges: [12354, 7065, 3998, 2202, 1285, 498, 256, 138] lux */ 88/* Available ranges: [12354, 7065, 3998, 2202, 1285, 498, 256, 138] lux */
86static const int us5182d_scales[] = {188500, 107800, 61000, 33600, 19600, 7600, 89static const int us5182d_scales[] = {188500, 107800, 61000, 33600, 19600, 7600,
@@ -300,6 +303,26 @@ static int us5182d_shutdown_en(struct us5182d_data *data, u8 state)
300 return ret; 303 return ret;
301} 304}
302 305
306
307static int us5182d_set_power_state(struct us5182d_data *data, bool on)
308{
309 int ret;
310
311 if (data->power_mode == US5182D_ONESHOT)
312 return 0;
313
314 if (on) {
315 ret = pm_runtime_get_sync(&data->client->dev);
316 if (ret < 0)
317 pm_runtime_put_noidle(&data->client->dev);
318 } else {
319 pm_runtime_mark_last_busy(&data->client->dev);
320 ret = pm_runtime_put_autosuspend(&data->client->dev);
321 }
322
323 return ret;
324}
325
303static int us5182d_read_raw(struct iio_dev *indio_dev, 326static int us5182d_read_raw(struct iio_dev *indio_dev,
304 struct iio_chan_spec const *chan, int *val, 327 struct iio_chan_spec const *chan, int *val,
305 int *val2, long mask) 328 int *val2, long mask)
@@ -317,15 +340,20 @@ static int us5182d_read_raw(struct iio_dev *indio_dev,
317 if (ret < 0) 340 if (ret < 0)
318 goto out_err; 341 goto out_err;
319 } 342 }
320 ret = us5182d_als_enable(data); 343 ret = us5182d_set_power_state(data, true);
321 if (ret < 0) 344 if (ret < 0)
322 goto out_err; 345 goto out_err;
323 346 ret = us5182d_als_enable(data);
347 if (ret < 0)
348 goto out_poweroff;
324 ret = us5182d_get_als(data); 349 ret = us5182d_get_als(data);
325 if (ret < 0) 350 if (ret < 0)
351 goto out_poweroff;
352 *val = ret;
353 ret = us5182d_set_power_state(data, false);
354 if (ret < 0)
326 goto out_err; 355 goto out_err;
327 mutex_unlock(&data->lock); 356 mutex_unlock(&data->lock);
328 *val = ret;
329 return IIO_VAL_INT; 357 return IIO_VAL_INT;
330 case IIO_PROXIMITY: 358 case IIO_PROXIMITY:
331 mutex_lock(&data->lock); 359 mutex_lock(&data->lock);
@@ -334,17 +362,22 @@ static int us5182d_read_raw(struct iio_dev *indio_dev,
334 if (ret < 0) 362 if (ret < 0)
335 goto out_err; 363 goto out_err;
336 } 364 }
337 ret = us5182d_px_enable(data); 365 ret = us5182d_set_power_state(data, true);
338 if (ret < 0) 366 if (ret < 0)
339 goto out_err; 367 goto out_err;
340 368 ret = us5182d_px_enable(data);
369 if (ret < 0)
370 goto out_poweroff;
341 ret = i2c_smbus_read_word_data(data->client, 371 ret = i2c_smbus_read_word_data(data->client,
342 US5182D_REG_PDL); 372 US5182D_REG_PDL);
343 if (ret < 0) 373 if (ret < 0)
374 goto out_poweroff;
375 *val = ret;
376 ret = us5182d_set_power_state(data, false);
377 if (ret < 0)
344 goto out_err; 378 goto out_err;
345 mutex_unlock(&data->lock); 379 mutex_unlock(&data->lock);
346 *val = ret; 380 return IIO_VAL_INT;
347 return IIO_VAL_INT;
348 default: 381 default:
349 return -EINVAL; 382 return -EINVAL;
350 } 383 }
@@ -363,6 +396,9 @@ static int us5182d_read_raw(struct iio_dev *indio_dev,
363 } 396 }
364 397
365 return -EINVAL; 398 return -EINVAL;
399
400out_poweroff:
401 us5182d_set_power_state(data, false);
366out_err: 402out_err:
367 mutex_unlock(&data->lock); 403 mutex_unlock(&data->lock);
368 return ret; 404 return ret;
@@ -579,6 +615,17 @@ static int us5182d_probe(struct i2c_client *client,
579 if (ret < 0) 615 if (ret < 0)
580 goto out_err; 616 goto out_err;
581 617
618 if (data->default_continuous) {
619 pm_runtime_set_active(&client->dev);
620 if (ret < 0)
621 goto out_err;
622 }
623
624 pm_runtime_enable(&client->dev);
625 pm_runtime_set_autosuspend_delay(&client->dev,
626 US5182D_SLEEP_MS);
627 pm_runtime_use_autosuspend(&client->dev);
628
582 ret = iio_device_register(indio_dev); 629 ret = iio_device_register(indio_dev);
583 if (ret < 0) 630 if (ret < 0)
584 goto out_err; 631 goto out_err;
@@ -597,9 +644,42 @@ static int us5182d_remove(struct i2c_client *client)
597 644
598 iio_device_unregister(i2c_get_clientdata(client)); 645 iio_device_unregister(i2c_get_clientdata(client));
599 646
647 pm_runtime_disable(&client->dev);
648 pm_runtime_set_suspended(&client->dev);
649
600 return us5182d_shutdown_en(data, US5182D_CFG0_SHUTDOWN_EN); 650 return us5182d_shutdown_en(data, US5182D_CFG0_SHUTDOWN_EN);
601} 651}
602 652
653#if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM)
654static int us5182d_suspend(struct device *dev)
655{
656 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
657 struct us5182d_data *data = iio_priv(indio_dev);
658
659 if (data->power_mode == US5182D_CONTINUOUS)
660 return us5182d_shutdown_en(data, US5182D_CFG0_SHUTDOWN_EN);
661
662 return 0;
663}
664
665static int us5182d_resume(struct device *dev)
666{
667 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
668 struct us5182d_data *data = iio_priv(indio_dev);
669
670 if (data->power_mode == US5182D_CONTINUOUS)
671 return us5182d_shutdown_en(data,
672 ~US5182D_CFG0_SHUTDOWN_EN & 0xff);
673
674 return 0;
675}
676#endif
677
678static const struct dev_pm_ops us5182d_pm_ops = {
679 SET_SYSTEM_SLEEP_PM_OPS(us5182d_suspend, us5182d_resume)
680 SET_RUNTIME_PM_OPS(us5182d_suspend, us5182d_resume, NULL)
681};
682
603static const struct acpi_device_id us5182d_acpi_match[] = { 683static const struct acpi_device_id us5182d_acpi_match[] = {
604 { "USD5182", 0}, 684 { "USD5182", 0},
605 {} 685 {}
@@ -617,6 +697,7 @@ MODULE_DEVICE_TABLE(i2c, us5182d_id);
617static struct i2c_driver us5182d_driver = { 697static struct i2c_driver us5182d_driver = {
618 .driver = { 698 .driver = {
619 .name = US5182D_DRV_NAME, 699 .name = US5182D_DRV_NAME,
700 .pm = &us5182d_pm_ops,
620 .acpi_match_table = ACPI_PTR(us5182d_acpi_match), 701 .acpi_match_table = ACPI_PTR(us5182d_acpi_match),
621 }, 702 },
622 .probe = us5182d_probe, 703 .probe = us5182d_probe,