aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIrina Tirdea <irina.tirdea@intel.com>2015-01-11 14:10:14 -0500
committerJonathan Cameron <jic23@kernel.org>2015-01-27 13:49:56 -0500
commit6da93a6710a3b1eb3d15b88bf96efaac322c893f (patch)
tree20559b13c30692024e43d6d2165b1f4832ba17a7
parent17a2cbc27981b85a09a48425c2614ae0cb7be8cd (diff)
iio: accel: mma9551: Add runtime pm support
Add support for runtime pm to reduce the power consumed by the device when not used. If CONFIG_PM is not enabled, the device will be powered on at init and only powered off on system suspend. If CONFIG_PM is enabled, runtime pm autosuspend is used: - for raw reads will keep the device on for a specified time - for events it will keep the device on as long as we have at least one event active Signed-off-by: Irina Tirdea <irina.tirdea@intel.com> Reviewed-by: Vlad Dogaru <vlad.dogaru@intel.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
-rw-r--r--drivers/iio/accel/mma9551.c162
1 files changed, 139 insertions, 23 deletions
diff --git a/drivers/iio/accel/mma9551.c b/drivers/iio/accel/mma9551.c
index 6563e267b8ae..f1a5a06a0726 100644
--- a/drivers/iio/accel/mma9551.c
+++ b/drivers/iio/accel/mma9551.c
@@ -22,6 +22,7 @@
22#include <linux/iio/iio.h> 22#include <linux/iio/iio.h>
23#include <linux/iio/sysfs.h> 23#include <linux/iio/sysfs.h>
24#include <linux/iio/events.h> 24#include <linux/iio/events.h>
25#include <linux/pm_runtime.h>
25 26
26#define MMA9551_DRV_NAME "mma9551" 27#define MMA9551_DRV_NAME "mma9551"
27#define MMA9551_IRQ_NAME "mma9551_event" 28#define MMA9551_IRQ_NAME "mma9551_event"
@@ -71,6 +72,7 @@ enum mma9551_gpio_pin {
71/* Sleep/Wake application */ 72/* Sleep/Wake application */
72#define MMA9551_SLEEP_CFG 0x06 73#define MMA9551_SLEEP_CFG 0x06
73#define MMA9551_SLEEP_CFG_SNCEN BIT(0) 74#define MMA9551_SLEEP_CFG_SNCEN BIT(0)
75#define MMA9551_SLEEP_CFG_FLEEN BIT(1)
74#define MMA9551_SLEEP_CFG_SCHEN BIT(2) 76#define MMA9551_SLEEP_CFG_SCHEN BIT(2)
75 77
76/* AFE application */ 78/* AFE application */
@@ -114,6 +116,9 @@ enum mma9551_tilt_axis {
114#define MMA9551_I2C_READ_RETRIES 5 116#define MMA9551_I2C_READ_RETRIES 5
115#define MMA9551_I2C_READ_DELAY 50 /* us */ 117#define MMA9551_I2C_READ_DELAY 50 /* us */
116 118
119#define MMA9551_DEFAULT_SAMPLE_RATE 122 /* Hz */
120#define MMA9551_AUTO_SUSPEND_DELAY_MS 2000
121
117struct mma9551_mbox_request { 122struct mma9551_mbox_request {
118 u8 start_mbox; /* Always 0. */ 123 u8 start_mbox; /* Always 0. */
119 u8 app_id; 124 u8 app_id;
@@ -387,16 +392,55 @@ static int mma9551_read_version(struct i2c_client *client)
387} 392}
388 393
389/* 394/*
395 * Power on chip and enable doze mode.
390 * Use 'false' as the second parameter to cause the device to enter 396 * Use 'false' as the second parameter to cause the device to enter
391 * sleep. 397 * sleep.
392 */ 398 */
393static int mma9551_set_device_state(struct i2c_client *client, 399static int mma9551_set_device_state(struct i2c_client *client, bool enable)
394 bool enable)
395{ 400{
396 return mma9551_update_config_bits(client, MMA9551_APPID_SLEEP_WAKE, 401 return mma9551_update_config_bits(client, MMA9551_APPID_SLEEP_WAKE,
397 MMA9551_SLEEP_CFG, 402 MMA9551_SLEEP_CFG,
398 MMA9551_SLEEP_CFG_SNCEN, 403 MMA9551_SLEEP_CFG_SNCEN |
399 enable ? 0 : MMA9551_SLEEP_CFG_SNCEN); 404 MMA9551_SLEEP_CFG_FLEEN |
405 MMA9551_SLEEP_CFG_SCHEN,
406 enable ? MMA9551_SLEEP_CFG_SCHEN |
407 MMA9551_SLEEP_CFG_FLEEN :
408 MMA9551_SLEEP_CFG_SNCEN);
409}
410
411static int mma9551_set_power_state(struct i2c_client *client, bool on)
412{
413#ifdef CONFIG_PM
414 int ret;
415
416 if (on)
417 ret = pm_runtime_get_sync(&client->dev);
418 else {
419 pm_runtime_mark_last_busy(&client->dev);
420 ret = pm_runtime_put_autosuspend(&client->dev);
421 }
422
423 if (ret < 0) {
424 dev_err(&client->dev,
425 "failed to change power state to %d\n", on);
426 if (on)
427 pm_runtime_put_noidle(&client->dev);
428
429 return ret;
430 }
431#endif
432
433 return 0;
434}
435
436static void mma9551_sleep(int freq)
437{
438 int sleep_val = 1000 / freq;
439
440 if (sleep_val < 20)
441 usleep_range(sleep_val * 1000, 20000);
442 else
443 msleep_interruptible(sleep_val);
400} 444}
401 445
402static int mma9551_read_incli_chan(struct i2c_client *client, 446static int mma9551_read_incli_chan(struct i2c_client *client,
@@ -424,15 +468,19 @@ static int mma9551_read_incli_chan(struct i2c_client *client,
424 return -EINVAL; 468 return -EINVAL;
425 } 469 }
426 470
471 ret = mma9551_set_power_state(client, true);
472 if (ret < 0)
473 return ret;
474
427 ret = mma9551_read_status_byte(client, MMA9551_APPID_TILT, 475 ret = mma9551_read_status_byte(client, MMA9551_APPID_TILT,
428 reg_addr, &angle); 476 reg_addr, &angle);
429 if (ret < 0) 477 if (ret < 0)
430 return ret; 478 goto out_poweroff;
431 479
432 ret = mma9551_read_status_byte(client, MMA9551_APPID_TILT, 480 ret = mma9551_read_status_byte(client, MMA9551_APPID_TILT,
433 MMA9551_TILT_QUAD_REG, &quadrant); 481 MMA9551_TILT_QUAD_REG, &quadrant);
434 if (ret < 0) 482 if (ret < 0)
435 return ret; 483 goto out_poweroff;
436 484
437 angle &= ~MMA9551_TILT_ANGFLG; 485 angle &= ~MMA9551_TILT_ANGFLG;
438 quadrant = (quadrant >> quad_shift) & 0x03; 486 quadrant = (quadrant >> quad_shift) & 0x03;
@@ -442,7 +490,11 @@ static int mma9551_read_incli_chan(struct i2c_client *client,
442 else 490 else
443 *val = angle + 90 * quadrant; 491 *val = angle + 90 * quadrant;
444 492
445 return IIO_VAL_INT; 493 ret = IIO_VAL_INT;
494
495out_poweroff:
496 mma9551_set_power_state(client, false);
497 return ret;
446} 498}
447 499
448static int mma9551_read_accel_chan(struct i2c_client *client, 500static int mma9551_read_accel_chan(struct i2c_client *client,
@@ -467,14 +519,22 @@ static int mma9551_read_accel_chan(struct i2c_client *client,
467 return -EINVAL; 519 return -EINVAL;
468 } 520 }
469 521
522 ret = mma9551_set_power_state(client, true);
523 if (ret < 0)
524 return ret;
525
470 ret = mma9551_read_status_word(client, MMA9551_APPID_AFE, 526 ret = mma9551_read_status_word(client, MMA9551_APPID_AFE,
471 reg_addr, &raw_accel); 527 reg_addr, &raw_accel);
472 if (ret < 0) 528 if (ret < 0)
473 return ret; 529 goto out_poweroff;
474 530
475 *val = raw_accel; 531 *val = raw_accel;
476 532
477 return IIO_VAL_INT; 533 ret = IIO_VAL_INT;
534
535out_poweroff:
536 mma9551_set_power_state(client, false);
537 return ret;
478} 538}
479 539
480static int mma9551_read_raw(struct iio_dev *indio_dev, 540static int mma9551_read_raw(struct iio_dev *indio_dev,
@@ -556,6 +616,10 @@ static int mma9551_config_incli_event(struct iio_dev *indio_dev,
556 MMA9551_APPID_NONE, 0, 0); 616 MMA9551_APPID_NONE, 0, 0);
557 if (ret < 0) 617 if (ret < 0)
558 return ret; 618 return ret;
619
620 ret = mma9551_set_power_state(data->client, false);
621 if (ret < 0)
622 return ret;
559 } else { 623 } else {
560 int bitnum; 624 int bitnum;
561 625
@@ -574,11 +638,18 @@ static int mma9551_config_incli_event(struct iio_dev *indio_dev,
574 return -EINVAL; 638 return -EINVAL;
575 } 639 }
576 640
641
642 ret = mma9551_set_power_state(data->client, true);
643 if (ret < 0)
644 return ret;
645
577 ret = mma9551_gpio_config(data->client, 646 ret = mma9551_gpio_config(data->client,
578 (enum mma9551_gpio_pin)mma_axis, 647 (enum mma9551_gpio_pin)mma_axis,
579 MMA9551_APPID_TILT, bitnum, 0); 648 MMA9551_APPID_TILT, bitnum, 0);
580 if (ret < 0) 649 if (ret < 0) {
650 mma9551_set_power_state(data->client, false);
581 return ret; 651 return ret;
652 }
582 } 653 }
583 654
584 data->event_enabled[mma_axis] = state; 655 data->event_enabled[mma_axis] = state;
@@ -771,12 +842,7 @@ static int mma9551_init(struct mma9551_data *data)
771 if (ret) 842 if (ret)
772 return ret; 843 return ret;
773 844
774 /* Power on chip and enable doze mode. */ 845 return mma9551_set_device_state(data->client, true);
775 return mma9551_update_config_bits(data->client,
776 MMA9551_APPID_SLEEP_WAKE,
777 MMA9551_SLEEP_CFG,
778 MMA9551_SLEEP_CFG_SCHEN | MMA9551_SLEEP_CFG_SNCEN,
779 MMA9551_SLEEP_CFG_SCHEN);
780} 846}
781 847
782static int mma9551_gpio_probe(struct iio_dev *indio_dev) 848static int mma9551_gpio_probe(struct iio_dev *indio_dev)
@@ -869,8 +935,19 @@ static int mma9551_probe(struct i2c_client *client,
869 goto out_poweroff; 935 goto out_poweroff;
870 } 936 }
871 937
938 ret = pm_runtime_set_active(&client->dev);
939 if (ret < 0)
940 goto out_iio_unregister;
941
942 pm_runtime_enable(&client->dev);
943 pm_runtime_set_autosuspend_delay(&client->dev,
944 MMA9551_AUTO_SUSPEND_DELAY_MS);
945 pm_runtime_use_autosuspend(&client->dev);
946
872 return 0; 947 return 0;
873 948
949out_iio_unregister:
950 iio_device_unregister(indio_dev);
874out_poweroff: 951out_poweroff:
875 mma9551_set_device_state(client, false); 952 mma9551_set_device_state(client, false);
876 953
@@ -882,6 +959,10 @@ static int mma9551_remove(struct i2c_client *client)
882 struct iio_dev *indio_dev = i2c_get_clientdata(client); 959 struct iio_dev *indio_dev = i2c_get_clientdata(client);
883 struct mma9551_data *data = iio_priv(indio_dev); 960 struct mma9551_data *data = iio_priv(indio_dev);
884 961
962 pm_runtime_disable(&client->dev);
963 pm_runtime_set_suspended(&client->dev);
964 pm_runtime_put_noidle(&client->dev);
965
885 iio_device_unregister(indio_dev); 966 iio_device_unregister(indio_dev);
886 mutex_lock(&data->mutex); 967 mutex_lock(&data->mutex);
887 mma9551_set_device_state(data->client, false); 968 mma9551_set_device_state(data->client, false);
@@ -890,37 +971,72 @@ static int mma9551_remove(struct i2c_client *client)
890 return 0; 971 return 0;
891} 972}
892 973
974#ifdef CONFIG_PM
975static int mma9551_runtime_suspend(struct device *dev)
976{
977 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
978 struct mma9551_data *data = iio_priv(indio_dev);
979 int ret;
980
981 mutex_lock(&data->mutex);
982 ret = mma9551_set_device_state(data->client, false);
983 mutex_unlock(&data->mutex);
984 if (ret < 0) {
985 dev_err(&data->client->dev, "powering off device failed\n");
986 return -EAGAIN;
987 }
988
989 return 0;
990}
991
992static int mma9551_runtime_resume(struct device *dev)
993{
994 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
995 struct mma9551_data *data = iio_priv(indio_dev);
996 int ret;
997
998 ret = mma9551_set_device_state(data->client, true);
999 if (ret < 0)
1000 return ret;
1001
1002 mma9551_sleep(MMA9551_DEFAULT_SAMPLE_RATE);
1003
1004 return 0;
1005}
1006#endif
1007
893#ifdef CONFIG_PM_SLEEP 1008#ifdef CONFIG_PM_SLEEP
894static int mma9551_suspend(struct device *dev) 1009static int mma9551_suspend(struct device *dev)
895{ 1010{
896 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 1011 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
897 struct mma9551_data *data = iio_priv(indio_dev); 1012 struct mma9551_data *data = iio_priv(indio_dev);
1013 int ret;
898 1014
899 mutex_lock(&data->mutex); 1015 mutex_lock(&data->mutex);
900 mma9551_set_device_state(data->client, false); 1016 ret = mma9551_set_device_state(data->client, false);
901 mutex_unlock(&data->mutex); 1017 mutex_unlock(&data->mutex);
902 1018
903 return 0; 1019 return ret;
904} 1020}
905 1021
906static int mma9551_resume(struct device *dev) 1022static int mma9551_resume(struct device *dev)
907{ 1023{
908 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 1024 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
909 struct mma9551_data *data = iio_priv(indio_dev); 1025 struct mma9551_data *data = iio_priv(indio_dev);
1026 int ret;
910 1027
911 mutex_lock(&data->mutex); 1028 mutex_lock(&data->mutex);
912 mma9551_set_device_state(data->client, true); 1029 ret = mma9551_set_device_state(data->client, true);
913 mutex_unlock(&data->mutex); 1030 mutex_unlock(&data->mutex);
914 1031
915 return 0; 1032 return ret;
916} 1033}
917#else
918#define mma9551_suspend NULL
919#define mma9551_resume NULL
920#endif 1034#endif
921 1035
922static const struct dev_pm_ops mma9551_pm_ops = { 1036static const struct dev_pm_ops mma9551_pm_ops = {
923 SET_SYSTEM_SLEEP_PM_OPS(mma9551_suspend, mma9551_resume) 1037 SET_SYSTEM_SLEEP_PM_OPS(mma9551_suspend, mma9551_resume)
1038 SET_RUNTIME_PM_OPS(mma9551_runtime_suspend,
1039 mma9551_runtime_resume, NULL)
924}; 1040};
925 1041
926static const struct acpi_device_id mma9551_acpi_match[] = { 1042static const struct acpi_device_id mma9551_acpi_match[] = {