From: Brian Masney <masneyb@onstation.org>
To: jic23@kernel.org, linux-iio@vger.kernel.org
Cc: gregkh@linuxfoundation.org, devel@driverdev.osuosl.org,
knaack.h@gmx.de, lars@metafoo.de, pmeerw@pmeerw.net,
linux-kernel@vger.kernel.org, ldewangan@nvidia.com
Subject: [PATCH v2 15/15] staging: iio: isl29028: add runtime power management support
Date: Tue, 17 Jan 2017 04:25:02 -0500 [thread overview]
Message-ID: <20170117092502.6951-16-masneyb@onstation.org> (raw)
In-Reply-To: <20170117092502.6951-1-masneyb@onstation.org>
This patch adds runtime power management support to the isl29028 driver.
It defaults to powering off the device after two seconds of inactivity.
isl29028_chip_init_and_power_on() currently only zeros the CONFIGURE
register on the chip, which will cause the chip to turn off. This patch
also renames that function to isl29028_clear_configure_reg() since it is
now used in several places.
Signed-off-by: Brian Masney <masneyb@onstation.org>
---
drivers/staging/iio/light/isl29028.c | 118 ++++++++++++++++++++++++++++++++---
1 file changed, 110 insertions(+), 8 deletions(-)
diff --git a/drivers/staging/iio/light/isl29028.c b/drivers/staging/iio/light/isl29028.c
index 598a5a5..a3264f7 100644
--- a/drivers/staging/iio/light/isl29028.c
+++ b/drivers/staging/iio/light/isl29028.c
@@ -26,6 +26,7 @@
#include <linux/regmap.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
+#include <linux/pm_runtime.h>
#define ISL29028_CONV_TIME_MS 100
@@ -60,6 +61,8 @@
#define ISL29028_NUM_REGS (ISL29028_REG_TEST2_MODE + 1)
+#define ISL29028_POWER_OFF_DELAY_MS 2000
+
enum isl29028_als_ir_mode {
ISL29028_MODE_NONE = 0,
ISL29028_MODE_ALS,
@@ -297,6 +300,23 @@ static int isl29028_ir_get(struct isl29028_chip *chip, int *ir_data)
return isl29028_read_als_ir(chip, ir_data);
}
+static int isl29028_set_pm_runtime_busy(struct isl29028_chip *chip, bool on)
+{
+ struct device *dev = regmap_get_device(chip->regmap);
+ int ret;
+
+ if (on) {
+ ret = pm_runtime_get_sync(dev);
+ if (ret < 0)
+ pm_runtime_put_noidle(dev);
+ } else {
+ pm_runtime_mark_last_busy(dev);
+ ret = pm_runtime_put_autosuspend(dev);
+ }
+
+ return ret;
+}
+
/* Channel IO */
static int isl29028_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
@@ -304,9 +324,15 @@ static int isl29028_write_raw(struct iio_dev *indio_dev,
{
struct isl29028_chip *chip = iio_priv(indio_dev);
struct device *dev = regmap_get_device(chip->regmap);
- int ret = -EINVAL;
+ int ret;
+
+ ret = isl29028_set_pm_runtime_busy(chip, true);
+ if (ret < 0)
+ return ret;
mutex_lock(&chip->lock);
+
+ ret = -EINVAL;
switch (chan->type) {
case IIO_PROXIMITY:
if (mask != IIO_CHAN_INFO_SAMP_FREQ) {
@@ -350,6 +376,13 @@ static int isl29028_write_raw(struct iio_dev *indio_dev,
mutex_unlock(&chip->lock);
+ if (ret < 0)
+ return ret;
+
+ ret = isl29028_set_pm_runtime_busy(chip, false);
+ if (ret < 0)
+ return ret;
+
return ret;
}
@@ -359,9 +392,15 @@ static int isl29028_read_raw(struct iio_dev *indio_dev,
{
struct isl29028_chip *chip = iio_priv(indio_dev);
struct device *dev = regmap_get_device(chip->regmap);
- int ret = -EINVAL;
+ int ret, pm_ret;
+
+ ret = isl29028_set_pm_runtime_busy(chip, true);
+ if (ret < 0)
+ return ret;
mutex_lock(&chip->lock);
+
+ ret = -EINVAL;
switch (mask) {
case IIO_CHAN_INFO_RAW:
case IIO_CHAN_INFO_PROCESSED:
@@ -405,6 +444,18 @@ static int isl29028_read_raw(struct iio_dev *indio_dev,
mutex_unlock(&chip->lock);
+ if (ret < 0)
+ return ret;
+
+ /**
+ * Preserve the ret variable if the call to
+ * isl29028_set_pm_runtime_busy() is successful so the reading
+ * (if applicable) is returned to user space.
+ */
+ pm_ret = isl29028_set_pm_runtime_busy(chip, false);
+ if (pm_ret < 0)
+ return pm_ret;
+
return ret;
}
@@ -445,17 +496,18 @@ static const struct iio_info isl29028_info = {
.write_raw = isl29028_write_raw,
};
-static int isl29028_chip_init_and_power_on(struct isl29028_chip *chip)
+static int isl29028_clear_configure_reg(struct isl29028_chip *chip)
{
struct device *dev = regmap_get_device(chip->regmap);
int ret;
ret = regmap_write(chip->regmap, ISL29028_REG_CONFIGURE, 0x0);
- if (ret < 0) {
+ if (ret < 0)
dev_err(dev, "%s(): Error %d clearing the CONFIGURE register\n",
__func__, ret);
- return ret;
- }
+
+ chip->als_ir_mode = ISL29028_MODE_NONE;
+ chip->enable_prox = false;
return ret;
}
@@ -509,7 +561,6 @@ static int isl29028_probe(struct i2c_client *client,
chip->enable_prox = false;
chip->prox_sampling = 20;
chip->lux_scale = 2000;
- chip->als_ir_mode = ISL29028_MODE_NONE;
ret = regmap_write(chip->regmap, ISL29028_REG_TEST1_MODE, 0x0);
if (ret < 0) {
@@ -527,7 +578,7 @@ static int isl29028_probe(struct i2c_client *client,
return ret;
}
- ret = isl29028_chip_init_and_power_on(chip);
+ ret = isl29028_clear_configure_reg(chip);
if (ret < 0)
return ret;
@@ -538,6 +589,11 @@ static int isl29028_probe(struct i2c_client *client,
indio_dev->dev.parent = &client->dev;
indio_dev->modes = INDIO_DIRECT_MODE;
+ pm_runtime_enable(&client->dev);
+ pm_runtime_set_autosuspend_delay(&client->dev,
+ ISL29028_POWER_OFF_DELAY_MS);
+ pm_runtime_use_autosuspend(&client->dev);
+
ret = devm_iio_device_register(indio_dev->dev.parent, indio_dev);
if (ret < 0) {
dev_err(&client->dev,
@@ -549,6 +605,50 @@ static int isl29028_probe(struct i2c_client *client,
return 0;
}
+static int isl29028_remove(struct i2c_client *client)
+{
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct isl29028_chip *chip = iio_priv(indio_dev);
+
+ iio_device_unregister(indio_dev);
+
+ pm_runtime_disable(&client->dev);
+ pm_runtime_set_suspended(&client->dev);
+ pm_runtime_put_noidle(&client->dev);
+
+ return isl29028_clear_configure_reg(chip);
+}
+
+static int __maybe_unused isl29028_suspend(struct device *dev)
+{
+ struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+ struct isl29028_chip *chip = iio_priv(indio_dev);
+ int ret;
+
+ mutex_lock(&chip->lock);
+
+ ret = isl29028_clear_configure_reg(chip);
+
+ mutex_unlock(&chip->lock);
+
+ return ret;
+}
+
+static int __maybe_unused isl29028_resume(struct device *dev)
+{
+ /**
+ * The specific component (ALS/IR or proximity) will enable itself as
+ * needed the next time that the user requests a reading. This is done
+ * above in isl29028_set_als_ir_mode() and isl29028_enable_proximity().
+ */
+ return 0;
+}
+
+static const struct dev_pm_ops isl29028_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(isl29028_suspend, isl29028_resume)
+ SET_RUNTIME_PM_OPS(isl29028_suspend, isl29028_resume, NULL)
+};
+
static const struct i2c_device_id isl29028_id[] = {
{"isl29028", 0},
{}
@@ -565,9 +665,11 @@ MODULE_DEVICE_TABLE(of, isl29028_of_match);
static struct i2c_driver isl29028_driver = {
.driver = {
.name = "isl29028",
+ .pm = &isl29028_pm_ops,
.of_match_table = isl29028_of_match,
},
.probe = isl29028_probe,
+ .remove = isl29028_remove,
.id_table = isl29028_id,
};
--
2.9.3
next prev parent reply other threads:[~2017-01-17 9:43 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-01-17 9:24 [PATCH v2 00/15] staging cleanups Brian Masney
2017-01-17 9:24 ` [PATCH v2 01/15] staging: iio: isl29028: made alignment of variables in struct isl29028_chip consistent Brian Masney
2017-01-21 14:29 ` Jonathan Cameron
2017-01-17 9:24 ` [PATCH v2 02/15] staging: iio: isl29028: fix alignment of function arguments Brian Masney
2017-01-21 14:30 ` Jonathan Cameron
2017-01-17 9:24 ` [PATCH v2 03/15] staging: iio: isl29028: combine isl29028_proxim_get() and isl29028_read_proxim() Brian Masney
2017-01-21 14:41 ` Jonathan Cameron
2017-01-17 9:24 ` [PATCH v2 04/15] staging: iio: isl29028: change newlines to improve readability Brian Masney
2017-01-21 14:41 ` Jonathan Cameron
2017-01-17 9:24 ` [PATCH v2 05/15] staging: iio: isl29028: remove unused define ISL29028_DEV_ATTR Brian Masney
2017-01-21 14:41 ` Jonathan Cameron
2017-01-17 9:24 ` [PATCH v2 06/15] staging: iio: isl29028: move failure logging into isl29028_set_proxim_sampling() Brian Masney
2017-01-21 14:37 ` Jonathan Cameron
2017-01-17 9:24 ` [PATCH v2 07/15] staging: iio: isl29028: move failure logging into isl29028_set_als_scale() Brian Masney
2017-01-21 14:42 ` Jonathan Cameron
2017-01-17 9:24 ` [PATCH v2 08/15] staging: iio: isl29028: made error messages consistent Brian Masney
2017-01-21 14:42 ` Jonathan Cameron
2017-01-17 9:24 ` [PATCH v2 09/15] staging: iio: isl29028: remove unnecessary error logging in isl29028_chip_init_and_power_on() Brian Masney
2017-01-21 14:42 ` Jonathan Cameron
2017-01-17 9:24 ` [PATCH v2 10/15] staging: iio: isl29028: remove out of memory log message Brian Masney
2017-01-21 14:43 ` Jonathan Cameron
2017-01-17 9:24 ` [PATCH v2 11/15] staging: iio: isl29028: remove unnecessary parenthesis Brian Masney
2017-01-21 14:43 ` Jonathan Cameron
2017-01-17 9:24 ` [PATCH v2 12/15] staging: iio: isl29028: remove enable flag from isl29028_enable_proximity() Brian Masney
2017-01-21 14:48 ` Jonathan Cameron
2017-01-17 9:25 ` [PATCH v2 13/15] staging: iio: isl29028: only set proximity sampling rate when proximity is enabled Brian Masney
2017-01-21 14:49 ` Jonathan Cameron
2017-01-17 9:25 ` [PATCH v2 14/15] staging: iio: isl29028: only set ALS scale when ALS/IR sensing " Brian Masney
2017-01-21 14:52 ` Jonathan Cameron
2017-01-17 9:25 ` Brian Masney [this message]
2017-01-21 14:58 ` [PATCH v2 15/15] staging: iio: isl29028: add runtime power management support Jonathan Cameron
2017-01-21 16:49 ` Brian Masney
2017-01-21 17:35 ` Jonathan Cameron
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170117092502.6951-16-masneyb@onstation.org \
--to=masneyb@onstation.org \
--cc=devel@driverdev.osuosl.org \
--cc=gregkh@linuxfoundation.org \
--cc=jic23@kernel.org \
--cc=knaack.h@gmx.de \
--cc=lars@metafoo.de \
--cc=ldewangan@nvidia.com \
--cc=linux-iio@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=pmeerw@pmeerw.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®