From: Jonathan Cameron <jic23@kernel.org>
To: Irina Tirdea <irina.tirdea@intel.com>, linux-iio@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, Vlad Dogaru <vlad.dogaru@intel.com>,
Daniel Baluta <daniel.baluta@intel.com>,
Hartmut Knaack <knaack.h@gmx.de>,
Lars-Peter Clausen <lars@metafoo.de>,
Peter Meerwald <pmeerw@pmeerw.net>
Subject: Re: [PATCH v2 08/10] iio: accel: mma9551: Add runtime pm support
Date: Mon, 26 Jan 2015 19:08:11 +0000 [thread overview]
Message-ID: <54C6909B.1060703@kernel.org> (raw)
In-Reply-To: <1421003416-27557-9-git-send-email-irina.tirdea@intel.com>
On 11/01/15 19:10, Irina Tirdea wrote:
> 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>
Looks good.
Applied to the togreg branch of iio.git
(at least we are driving down the size of the patch set for the next
revision!)
Jonathan
> ---
> drivers/iio/accel/mma9551.c | 162 +++++++++++++++++++++++++++++++++++++-------
> 1 file changed, 139 insertions(+), 23 deletions(-)
>
> diff --git a/drivers/iio/accel/mma9551.c b/drivers/iio/accel/mma9551.c
> index 6563e26..f1a5a06 100644
> --- a/drivers/iio/accel/mma9551.c
> +++ b/drivers/iio/accel/mma9551.c
> @@ -22,6 +22,7 @@
> #include <linux/iio/iio.h>
> #include <linux/iio/sysfs.h>
> #include <linux/iio/events.h>
> +#include <linux/pm_runtime.h>
>
> #define MMA9551_DRV_NAME "mma9551"
> #define MMA9551_IRQ_NAME "mma9551_event"
> @@ -71,6 +72,7 @@ enum mma9551_gpio_pin {
> /* Sleep/Wake application */
> #define MMA9551_SLEEP_CFG 0x06
> #define MMA9551_SLEEP_CFG_SNCEN BIT(0)
> +#define MMA9551_SLEEP_CFG_FLEEN BIT(1)
> #define MMA9551_SLEEP_CFG_SCHEN BIT(2)
>
> /* AFE application */
> @@ -114,6 +116,9 @@ enum mma9551_tilt_axis {
> #define MMA9551_I2C_READ_RETRIES 5
> #define MMA9551_I2C_READ_DELAY 50 /* us */
>
> +#define MMA9551_DEFAULT_SAMPLE_RATE 122 /* Hz */
> +#define MMA9551_AUTO_SUSPEND_DELAY_MS 2000
> +
> struct mma9551_mbox_request {
> u8 start_mbox; /* Always 0. */
> u8 app_id;
> @@ -387,16 +392,55 @@ static int mma9551_read_version(struct i2c_client *client)
> }
>
> /*
> + * Power on chip and enable doze mode.
> * Use 'false' as the second parameter to cause the device to enter
> * sleep.
> */
> -static int mma9551_set_device_state(struct i2c_client *client,
> - bool enable)
> +static int mma9551_set_device_state(struct i2c_client *client, bool enable)
> {
> return mma9551_update_config_bits(client, MMA9551_APPID_SLEEP_WAKE,
> MMA9551_SLEEP_CFG,
> - MMA9551_SLEEP_CFG_SNCEN,
> - enable ? 0 : MMA9551_SLEEP_CFG_SNCEN);
> + MMA9551_SLEEP_CFG_SNCEN |
> + MMA9551_SLEEP_CFG_FLEEN |
> + MMA9551_SLEEP_CFG_SCHEN,
> + enable ? MMA9551_SLEEP_CFG_SCHEN |
> + MMA9551_SLEEP_CFG_FLEEN :
> + MMA9551_SLEEP_CFG_SNCEN);
> +}
> +
> +static int mma9551_set_power_state(struct i2c_client *client, bool on)
> +{
> +#ifdef CONFIG_PM
> + int ret;
> +
> + if (on)
> + ret = pm_runtime_get_sync(&client->dev);
> + else {
> + pm_runtime_mark_last_busy(&client->dev);
> + ret = pm_runtime_put_autosuspend(&client->dev);
> + }
> +
> + if (ret < 0) {
> + dev_err(&client->dev,
> + "failed to change power state to %d\n", on);
> + if (on)
> + pm_runtime_put_noidle(&client->dev);
> +
> + return ret;
> + }
> +#endif
> +
> + return 0;
> +}
> +
> +static void mma9551_sleep(int freq)
> +{
> + int sleep_val = 1000 / freq;
> +
> + if (sleep_val < 20)
> + usleep_range(sleep_val * 1000, 20000);
> + else
> + msleep_interruptible(sleep_val);
> }
>
> static int mma9551_read_incli_chan(struct i2c_client *client,
> @@ -424,15 +468,19 @@ static int mma9551_read_incli_chan(struct i2c_client *client,
> return -EINVAL;
> }
>
> + ret = mma9551_set_power_state(client, true);
> + if (ret < 0)
> + return ret;
> +
> ret = mma9551_read_status_byte(client, MMA9551_APPID_TILT,
> reg_addr, &angle);
> if (ret < 0)
> - return ret;
> + goto out_poweroff;
>
> ret = mma9551_read_status_byte(client, MMA9551_APPID_TILT,
> MMA9551_TILT_QUAD_REG, &quadrant);
> if (ret < 0)
> - return ret;
> + goto out_poweroff;
>
> angle &= ~MMA9551_TILT_ANGFLG;
> quadrant = (quadrant >> quad_shift) & 0x03;
> @@ -442,7 +490,11 @@ static int mma9551_read_incli_chan(struct i2c_client *client,
> else
> *val = angle + 90 * quadrant;
>
> - return IIO_VAL_INT;
> + ret = IIO_VAL_INT;
> +
> +out_poweroff:
> + mma9551_set_power_state(client, false);
> + return ret;
> }
>
> static int mma9551_read_accel_chan(struct i2c_client *client,
> @@ -467,14 +519,22 @@ static int mma9551_read_accel_chan(struct i2c_client *client,
> return -EINVAL;
> }
>
> + ret = mma9551_set_power_state(client, true);
> + if (ret < 0)
> + return ret;
> +
> ret = mma9551_read_status_word(client, MMA9551_APPID_AFE,
> reg_addr, &raw_accel);
> if (ret < 0)
> - return ret;
> + goto out_poweroff;
>
> *val = raw_accel;
>
> - return IIO_VAL_INT;
> + ret = IIO_VAL_INT;
> +
> +out_poweroff:
> + mma9551_set_power_state(client, false);
> + return ret;
> }
>
> static int mma9551_read_raw(struct iio_dev *indio_dev,
> @@ -556,6 +616,10 @@ static int mma9551_config_incli_event(struct iio_dev *indio_dev,
> MMA9551_APPID_NONE, 0, 0);
> if (ret < 0)
> return ret;
> +
> + ret = mma9551_set_power_state(data->client, false);
> + if (ret < 0)
> + return ret;
> } else {
> int bitnum;
>
> @@ -574,11 +638,18 @@ static int mma9551_config_incli_event(struct iio_dev *indio_dev,
> return -EINVAL;
> }
>
> +
Trivial but one blank line here is enough...
> + ret = mma9551_set_power_state(data->client, true);
> + if (ret < 0)
> + return ret;
> +
> ret = mma9551_gpio_config(data->client,
> (enum mma9551_gpio_pin)mma_axis,
> MMA9551_APPID_TILT, bitnum, 0);
> - if (ret < 0)
> + if (ret < 0) {
> + mma9551_set_power_state(data->client, false);
> return ret;
> + }
> }
>
> data->event_enabled[mma_axis] = state;
> @@ -771,12 +842,7 @@ static int mma9551_init(struct mma9551_data *data)
> if (ret)
> return ret;
>
> - /* Power on chip and enable doze mode. */
> - return mma9551_update_config_bits(data->client,
> - MMA9551_APPID_SLEEP_WAKE,
> - MMA9551_SLEEP_CFG,
> - MMA9551_SLEEP_CFG_SCHEN | MMA9551_SLEEP_CFG_SNCEN,
> - MMA9551_SLEEP_CFG_SCHEN);
> + return mma9551_set_device_state(data->client, true);
> }
>
> static int mma9551_gpio_probe(struct iio_dev *indio_dev)
> @@ -869,8 +935,19 @@ static int mma9551_probe(struct i2c_client *client,
> goto out_poweroff;
> }
>
> + ret = pm_runtime_set_active(&client->dev);
> + if (ret < 0)
> + goto out_iio_unregister;
> +
> + pm_runtime_enable(&client->dev);
> + pm_runtime_set_autosuspend_delay(&client->dev,
> + MMA9551_AUTO_SUSPEND_DELAY_MS);
> + pm_runtime_use_autosuspend(&client->dev);
> +
> return 0;
>
> +out_iio_unregister:
> + iio_device_unregister(indio_dev);
> out_poweroff:
> mma9551_set_device_state(client, false);
>
> @@ -882,6 +959,10 @@ static int mma9551_remove(struct i2c_client *client)
> struct iio_dev *indio_dev = i2c_get_clientdata(client);
> struct mma9551_data *data = iio_priv(indio_dev);
>
> + pm_runtime_disable(&client->dev);
> + pm_runtime_set_suspended(&client->dev);
> + pm_runtime_put_noidle(&client->dev);
> +
> iio_device_unregister(indio_dev);
> mutex_lock(&data->mutex);
> mma9551_set_device_state(data->client, false);
> @@ -890,37 +971,72 @@ static int mma9551_remove(struct i2c_client *client)
> return 0;
> }
>
> +#ifdef CONFIG_PM
> +static int mma9551_runtime_suspend(struct device *dev)
> +{
> + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
> + struct mma9551_data *data = iio_priv(indio_dev);
> + int ret;
> +
> + mutex_lock(&data->mutex);
> + ret = mma9551_set_device_state(data->client, false);
> + mutex_unlock(&data->mutex);
> + if (ret < 0) {
> + dev_err(&data->client->dev, "powering off device failed\n");
> + return -EAGAIN;
> + }
> +
> + return 0;
> +}
> +
> +static int mma9551_runtime_resume(struct device *dev)
> +{
> + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
> + struct mma9551_data *data = iio_priv(indio_dev);
> + int ret;
> +
> + ret = mma9551_set_device_state(data->client, true);
> + if (ret < 0)
> + return ret;
> +
> + mma9551_sleep(MMA9551_DEFAULT_SAMPLE_RATE);
> +
> + return 0;
> +}
> +#endif
> +
> #ifdef CONFIG_PM_SLEEP
> static int mma9551_suspend(struct device *dev)
> {
> struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
> struct mma9551_data *data = iio_priv(indio_dev);
> + int ret;
>
> mutex_lock(&data->mutex);
> - mma9551_set_device_state(data->client, false);
> + ret = mma9551_set_device_state(data->client, false);
> mutex_unlock(&data->mutex);
>
> - return 0;
> + return ret;
> }
>
> static int mma9551_resume(struct device *dev)
> {
> struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
> struct mma9551_data *data = iio_priv(indio_dev);
> + int ret;
>
> mutex_lock(&data->mutex);
> - mma9551_set_device_state(data->client, true);
> + ret = mma9551_set_device_state(data->client, true);
> mutex_unlock(&data->mutex);
>
> - return 0;
> + return ret;
> }
> -#else
> -#define mma9551_suspend NULL
> -#define mma9551_resume NULL
> #endif
>
> static const struct dev_pm_ops mma9551_pm_ops = {
> SET_SYSTEM_SLEEP_PM_OPS(mma9551_suspend, mma9551_resume)
> + SET_RUNTIME_PM_OPS(mma9551_runtime_suspend,
> + mma9551_runtime_resume, NULL)
> };
>
> static const struct acpi_device_id mma9551_acpi_match[] = {
>
next prev parent reply other threads:[~2015-01-26 19:08 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-01-11 19:10 [PATCH v2 00/10] Add MMA9553 driver & PM support for MMA9551 Irina Tirdea
2015-01-11 19:10 ` [PATCH v2 01/10] iio: core: Introduce ENERGY channel type Irina Tirdea
2015-01-25 22:58 ` Jonathan Cameron
2015-03-29 0:14 ` Hartmut Knaack
2015-03-30 11:18 ` Tirdea, Irina
2015-01-11 19:10 ` [PATCH v2 02/10] iio: core: Introduce DISTANCE " Irina Tirdea
2015-01-25 22:59 ` Jonathan Cameron
2015-01-11 19:10 ` [PATCH v2 03/10] iio: core: Introduce IIO_VELOCITY and IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z Irina Tirdea
2015-01-25 23:00 ` Jonathan Cameron
2015-01-11 19:10 ` [PATCH v2 04/10] iio: core: Introduce IO_CHAN_INFO_CALIBWEIGHT Irina Tirdea
2015-01-25 23:01 ` Jonathan Cameron
2015-01-11 19:10 ` [PATCH v2 05/10] iio: core: Introduce CHANGE event type Irina Tirdea
2015-01-25 23:03 ` Jonathan Cameron
2015-01-11 19:10 ` [PATCH v2 06/10] iio: core: Remove IIO_EV_TYPE_INSTANCE Irina Tirdea
2015-01-26 19:04 ` Jonathan Cameron
2015-01-11 19:10 ` [PATCH v2 07/10] iio: core: Introduce IIO_CHAN_INFO_FILTER_OUTLIERS_THRESH and _PERIOD Irina Tirdea
2015-01-25 23:07 ` Jonathan Cameron
2015-01-26 14:40 ` Daniel Baluta
2015-01-26 19:01 ` Jonathan Cameron
2015-01-27 16:20 ` Tirdea, Irina
2015-01-27 16:20 ` Tirdea, Irina
2015-01-11 19:10 ` [PATCH v2 08/10] iio: accel: mma9551: Add runtime pm support Irina Tirdea
2015-01-26 19:08 ` Jonathan Cameron [this message]
2015-01-27 17:18 ` Tirdea, Irina
2015-01-27 17:18 ` Tirdea, Irina
2015-01-11 19:10 ` [PATCH v2 09/10] iio: accel: mma9551: split driver to expose mma955x api Irina Tirdea
2015-01-26 19:25 ` Jonathan Cameron
2015-01-11 19:10 ` [PATCH v2 10/10] iio: add driver for Freescale MMA9553 Irina Tirdea
2015-01-26 20:44 ` Jonathan Cameron
2015-01-27 17:09 ` Tirdea, Irina
2015-01-27 17:09 ` Tirdea, Irina
2015-01-27 17:31 ` Jonathan Cameron
2015-01-27 17:31 ` 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=54C6909B.1060703@kernel.org \
--to=jic23@kernel.org \
--cc=daniel.baluta@intel.com \
--cc=irina.tirdea@intel.com \
--cc=knaack.h@gmx.de \
--cc=lars@metafoo.de \
--cc=linux-iio@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=pmeerw@pmeerw.net \
--cc=vlad.dogaru@intel.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.