diff mbox

[RFC,2/2] regulator: qcom-rpm: Implement RPM assisted disable

Message ID 1415659966-16200-3-git-send-email-bjorn.andersson@sonymobile.com (mailing list archive)
State New, archived
Headers show

Commit Message

Bjorn Andersson Nov. 10, 2014, 10:52 p.m. UTC
Some regulators are used to power e.g. PLLs that clocks the core we're
running on, so we can't turn them off directly; but we do want them off
when the core is powered down. To handle this the Qualcomm SoC provides
a means to specify a "sleep state" for RPM resources that can be
triggered by the hardware when the cores are brought down.

Resources of this type should be considered always-on while the CPU(s)
are running and we can utilize the "sleep state" functionality to defer
disabling them until the CPU(s) go to sleep, if not used by other
peripherals at that time.

Other properties are kept in sync between the states, so that if the
CPU(s) go to sleep with a particular regulator still enabled there will
be no change.

Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
---
 Documentation/devicetree/bindings/mfd/qcom-rpm.txt |   28 ++++++++
 drivers/regulator/qcom_rpm-regulator.c             |   68 +++++++++++++++-----
 2 files changed, 79 insertions(+), 17 deletions(-)

Comments

Andreas Färber Nov. 11, 2014, 9:11 a.m. UTC | #1
Hi,

Am 10.11.2014 um 23:52 schrieb Bjorn Andersson:
> diff --git a/Documentation/devicetree/bindings/mfd/qcom-rpm.txt b/Documentation/devicetree/bindings/mfd/qcom-rpm.txt
> index 4264021..4671eef 100644
> --- a/Documentation/devicetree/bindings/mfd/qcom-rpm.txt
> +++ b/Documentation/devicetree/bindings/mfd/qcom-rpm.txt
> @@ -112,6 +112,13 @@ of valid subnodes that can operate on these resources.
>  	Definition: select that the power supply should operate in hysteretic
>  		    mode, instead of the default pwm mode
>  
> +- qcom,rpm-assisted-disable:
> +	Usage: optional
> +	Value type: <empty>
> +	Definition: select that the regulator is supplying the active CPU(s)
> +		    and can only be disabled with the assistans from the RPM

"assistance"

> +		    after going to sleep
> +
>  Standard regulator bindings are used inside switch mode power supply subnodes.
>  Check Documentation/devicetree/bindings/regulator/regulator.txt for more
>  details.
> @@ -160,6 +167,13 @@ details.
>  						qcom,rpm-pm8921-nldo,
>  						qcom,rpm-pm8921-nldo1200
>  
> +- qcom,rpm-assisted-disable:
> +	Usage: optional
> +	Value type: <empty>
> +	Definition: select that the regulator is supplying the active CPU(s)
> +		    and can only be disabled with the assistans from the RPM

ditto

> +		    after going to sleep
> +
>  Standard regulator bindings are used inside switch low-dropout regulator
>  subnodes.  Check Documentation/devicetree/bindings/regulator/regulator.txt for
>  more details.
> @@ -190,6 +204,13 @@ more details.
>  		    2740000, 2400000, 2130000, 1920000, 1750000, 1600000,
>  		    1480000, 1370000, 1280000, 1200000
>  
> +- qcom,rpm-assisted-disable:
> +	Usage: optional
> +	Value type: <empty>
> +	Definition: select that the regulator is supplying the active CPU(s)
> +		    and can only be disabled with the assistans from the RPM

ditto

> +		    after going to sleep
> +
>  Standard regulator bindings are used inside negative charge pump regulator
>  subnodes.  Check Documentation/devicetree/bindings/regulator/regulator.txt for
>  more details.
> @@ -215,6 +236,13 @@ more details.
>  		    QCOM_RPM_PM8921_LVS1 - QCOM_RPM_PM8921_LVS7,
>  		    QCOM_RPM_PM8921_MVS
>  
> +- qcom,rpm-assisted-disable:
> +	Usage: optional
> +	Value type: <empty>
> +	Definition: select that the regulator is supplying the active CPU(s)
> +		    and can only be disabled with the assistans from the RPM

ditto

> +		    after going to sleep
> +
>  = EXAMPLE
>  
>  	#include <dt-bindings/mfd/qcom-rpm.h>
[snip]

Regards,
Andreas
Lee Jones Nov. 11, 2014, 11:59 a.m. UTC | #2
On Mon, 10 Nov 2014, Bjorn Andersson wrote:

> Some regulators are used to power e.g. PLLs that clocks the core we're
> running on, so we can't turn them off directly; but we do want them off
> when the core is powered down. To handle this the Qualcomm SoC provides
> a means to specify a "sleep state" for RPM resources that can be
> triggered by the hardware when the cores are brought down.
> 
> Resources of this type should be considered always-on while the CPU(s)
> are running and we can utilize the "sleep state" functionality to defer
> disabling them until the CPU(s) go to sleep, if not used by other
> peripherals at that time.
> 
> Other properties are kept in sync between the states, so that if the
> CPU(s) go to sleep with a particular regulator still enabled there will
> be no change.
> 
> Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
> ---
>  Documentation/devicetree/bindings/mfd/qcom-rpm.txt |   28 ++++++++

Please place this into a seperate patch.

See: Documentation/devicetree/bindings/submitting-patches.txt

>  drivers/regulator/qcom_rpm-regulator.c             |   68 +++++++++++++++-----
>  2 files changed, 79 insertions(+), 17 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/mfd/qcom-rpm.txt b/Documentation/devicetree/bindings/mfd/qcom-rpm.txt
> index 4264021..4671eef 100644
> --- a/Documentation/devicetree/bindings/mfd/qcom-rpm.txt
> +++ b/Documentation/devicetree/bindings/mfd/qcom-rpm.txt
> @@ -112,6 +112,13 @@ of valid subnodes that can operate on these resources.
>  	Definition: select that the power supply should operate in hysteretic
>  		    mode, instead of the default pwm mode
>  
> +- qcom,rpm-assisted-disable:
> +	Usage: optional
> +	Value type: <empty>
> +	Definition: select that the regulator is supplying the active CPU(s)
> +		    and can only be disabled with the assistans from the RPM
> +		    after going to sleep
> +

This requires a DT Ack.

>  Standard regulator bindings are used inside switch mode power supply subnodes.
>  Check Documentation/devicetree/bindings/regulator/regulator.txt for more
>  details.
> @@ -160,6 +167,13 @@ details.
>  						qcom,rpm-pm8921-nldo,
>  						qcom,rpm-pm8921-nldo1200
>  
> +- qcom,rpm-assisted-disable:
> +	Usage: optional
> +	Value type: <empty>
> +	Definition: select that the regulator is supplying the active CPU(s)
> +		    and can only be disabled with the assistans from the RPM
> +		    after going to sleep
> +

Eh?  I think I'm seeing double.

>  Standard regulator bindings are used inside switch low-dropout regulator
>  subnodes.  Check Documentation/devicetree/bindings/regulator/regulator.txt for
>  more details.
> @@ -190,6 +204,13 @@ more details.
>  		    2740000, 2400000, 2130000, 1920000, 1750000, 1600000,
>  		    1480000, 1370000, 1280000, 1200000
>  
> +- qcom,rpm-assisted-disable:
> +	Usage: optional
> +	Value type: <empty>
> +	Definition: select that the regulator is supplying the active CPU(s)
> +		    and can only be disabled with the assistans from the RPM
> +		    after going to sleep
> +

Triple?

>  Standard regulator bindings are used inside negative charge pump regulator
>  subnodes.  Check Documentation/devicetree/bindings/regulator/regulator.txt for
>  more details.
> @@ -215,6 +236,13 @@ more details.
>  		    QCOM_RPM_PM8921_LVS1 - QCOM_RPM_PM8921_LVS7,
>  		    QCOM_RPM_PM8921_MVS
>  
> +- qcom,rpm-assisted-disable:
> +	Usage: optional
> +	Value type: <empty>
> +	Definition: select that the regulator is supplying the active CPU(s)
> +		    and can only be disabled with the assistans from the RPM
> +		    after going to sleep
> +

There must be a better way to document this.

>  = EXAMPLE
>  
>  	#include <dt-bindings/mfd/qcom-rpm.h>

[...]
Javier Martinez Canillas Nov. 11, 2014, 2:21 p.m. UTC | #3
Hello Bjorn,

On Mon, Nov 10, 2014 at 11:52 PM, Bjorn Andersson
<bjorn.andersson@sonymobile.com> wrote:
> Some regulators are used to power e.g. PLLs that clocks the core we're
> running on, so we can't turn them off directly; but we do want them off
> when the core is powered down. To handle this the Qualcomm SoC provides
> a means to specify a "sleep state" for RPM resources that can be
> triggered by the hardware when the cores are brought down.
>

The regulator core already has support to control the state of
regulators when the system enters into a sleep state. Now the generic
regulator DT binding has also been extended to support defining if a
regulator should be "regulator-{on,off}-in-suspend". Please take a
look at the topic/suspend branch [0] in the regulator tree that has
the latest binding.

If that is not enough for your hardware and use case, I've been
working on adding initial and suspend mode for regulators. The latest
series is [1] and the needed bits for the max77802 regulator driver is
[2].

It's always better to use existing functionality if possible, instead
of adding custom per driver DT bindings. So it would be great if you
can take a look to the mentioned patches.

>  Documentation/devicetree/bindings/mfd/qcom-rpm.txt |   28 ++++++++
>  drivers/regulator/qcom_rpm-regulator.c             |   68 +++++++++++++++-----

Against which tree this patch has been developed? afaict
Documentation/devicetree/bindings/mfd/qcom-rpm.txt does not exist even
in the latest for-next [3] branch of the mfd tree.

>
>         #include <dt-bindings/mfd/qcom-rpm.h>

This file doesn't exit either and the regulator driver depends on
MFD_QCOM_RPM which also is not present in mainline.

By looking at the mail archives I see that you posted both the
regulator and mfd driver in the same series [4] but only the regulator
driver was picked by Mark so I guess Lee has to pick the mfd driver in
order to allow the regulator driver to be built.

Best regards,
Javier

[0]: https://git.kernel.org/cgit/linux/kernel/git/broonie/regulator.git/log/?h=topic/suspend
[1]: https://lkml.org/lkml/2014/11/10/325
[2]: https://lkml.org/lkml/2014/11/11/403
[3]: https://git.kernel.org/cgit/linux/kernel/git/lee/mfd.git/log/?h=for-mfd-next
[4]: https://lkml.org/lkml/2014/9/22/731
Bjorn Andersson Nov. 11, 2014, 6:34 p.m. UTC | #4
On Tue 11 Nov 01:11 PST 2014, Andreas F?rber wrote:

> Hi,
> 
> Am 10.11.2014 um 23:52 schrieb Bjorn Andersson:
> > diff --git a/Documentation/devicetree/bindings/mfd/qcom-rpm.txt b/Documentation/devicetree/bindings/mfd/qcom-rpm.txt
> > index 4264021..4671eef 100644
> > --- a/Documentation/devicetree/bindings/mfd/qcom-rpm.txt
> > +++ b/Documentation/devicetree/bindings/mfd/qcom-rpm.txt
> > @@ -112,6 +112,13 @@ of valid subnodes that can operate on these resources.
> >  	Definition: select that the power supply should operate in hysteretic
> >  		    mode, instead of the default pwm mode
> >  
> > +- qcom,rpm-assisted-disable:
> > +	Usage: optional
> > +	Value type: <empty>
> > +	Definition: select that the regulator is supplying the active CPU(s)
> > +		    and can only be disabled with the assistans from the RPM
> 
> "assistance"
> 

Thanks

Regards,
Bjorn
Bjorn Andersson Nov. 11, 2014, 6:39 p.m. UTC | #5
On Tue 11 Nov 03:59 PST 2014, Lee Jones wrote:

> On Mon, 10 Nov 2014, Bjorn Andersson wrote:
> 
> > Some regulators are used to power e.g. PLLs that clocks the core we're
> > running on, so we can't turn them off directly; but we do want them off
> > when the core is powered down. To handle this the Qualcomm SoC provides
> > a means to specify a "sleep state" for RPM resources that can be
> > triggered by the hardware when the cores are brought down.
> > 
> > Resources of this type should be considered always-on while the CPU(s)
> > are running and we can utilize the "sleep state" functionality to defer
> > disabling them until the CPU(s) go to sleep, if not used by other
> > peripherals at that time.
> > 
> > Other properties are kept in sync between the states, so that if the
> > CPU(s) go to sleep with a particular regulator still enabled there will
> > be no change.
> > 
> > Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
> > ---
> >  Documentation/devicetree/bindings/mfd/qcom-rpm.txt |   28 ++++++++
> 
> Please place this into a seperate patch.
> 
> See: Documentation/devicetree/bindings/submitting-patches.txt
> 

Yes, I'm aware. As you probably remember we still haven't gotten an ack on the
original file, so given the outcome of the discussion of the design of this I
plan to fold it into the original patch and send out a new version.

> >  drivers/regulator/qcom_rpm-regulator.c             |   68 +++++++++++++++-----
> >  2 files changed, 79 insertions(+), 17 deletions(-)
> > 
> > diff --git a/Documentation/devicetree/bindings/mfd/qcom-rpm.txt b/Documentation/devicetree/bindings/mfd/qcom-rpm.txt
> > index 4264021..4671eef 100644
> > --- a/Documentation/devicetree/bindings/mfd/qcom-rpm.txt
> > +++ b/Documentation/devicetree/bindings/mfd/qcom-rpm.txt
> > @@ -112,6 +112,13 @@ of valid subnodes that can operate on these resources.
> >  	Definition: select that the power supply should operate in hysteretic
> >  		    mode, instead of the default pwm mode
> >  
> > +- qcom,rpm-assisted-disable:
> > +	Usage: optional
> > +	Value type: <empty>
> > +	Definition: select that the regulator is supplying the active CPU(s)
> > +		    and can only be disabled with the assistans from the RPM
> > +		    after going to sleep
> > +
> 
> This requires a DT Ack.
> 

The entire file still requires a dt ack, but the "sleep state" will change the
binding so let's see where this RFC takes us.

I would have preferred if someone gave me the "sleep state" feedback once we
had this out for review, but it didn't reach the right people at Qualcomm at
the time.

> >  Standard regulator bindings are used inside switch mode power supply subnodes.
> >  Check Documentation/devicetree/bindings/regulator/regulator.txt for more
> >  details.
> > @@ -160,6 +167,13 @@ details.
> >  						qcom,rpm-pm8921-nldo,
> >  						qcom,rpm-pm8921-nldo1200
> >  
> > +- qcom,rpm-assisted-disable:
> > +	Usage: optional
> > +	Value type: <empty>
> > +	Definition: select that the regulator is supplying the active CPU(s)
> > +		    and can only be disabled with the assistans from the RPM
> > +		    after going to sleep
> > +
> 
> Eh?  I think I'm seeing double.
> 

You're right, it would make sense to move this to a "common subnode properties"
section.

Regards,
Bjorn
Bjorn Andersson Nov. 11, 2014, 7:23 p.m. UTC | #6
On Tue 11 Nov 06:21 PST 2014, Javier Martinez Canillas wrote:

> Hello Bjorn,
> 

Hi Javier,

> On Mon, Nov 10, 2014 at 11:52 PM, Bjorn Andersson
> <bjorn.andersson@sonymobile.com> wrote:
> > Some regulators are used to power e.g. PLLs that clocks the core we're
> > running on, so we can't turn them off directly; but we do want them off
> > when the core is powered down. To handle this the Qualcomm SoC provides
> > a means to specify a "sleep state" for RPM resources that can be
> > triggered by the hardware when the cores are brought down.
> >
> 
> The regulator core already has support to control the state of
> regulators when the system enters into a sleep state. Now the generic
> regulator DT binding has also been extended to support defining if a
> regulator should be "regulator-{on,off}-in-suspend". Please take a
> look at the topic/suspend branch [0] in the regulator tree that has
> the latest binding.
> 

I was planning to utilize the suspend states functionality in the core and was
looking at implementing [0] myself, so glad that's coming in place.

However, as a practical example we have LDO12 on the MSM8974 SoC that is used
for powering CPU PLLs, WiFi/BT PLLs, display, camera sensor and hdmi.

In a phone it's most reasonable to expect the WiFi core keeping a vote for the
regulators to be enabled during a suspend, but if you're in airplane mode (or
WiFi is turned off) you want to save the power - so it's not possible to
configure this statically.

Further more, the CPU vote is not tied to suspend state but rather cpuidle
state. It's not unreasonable to think of a state where we're clocking out
pixels to the display in Android with the CPU turned off and hence the CPU PLL
vote lifted.

> If that is not enough for your hardware and use case, I've been
> working on adding initial and suspend mode for regulators. The latest
> series is [1] and the needed bits for the max77802 regulator driver is
> [2].
> 

Looks good.

> It's always better to use existing functionality if possible, instead
> of adding custom per driver DT bindings. So it would be great if you
> can take a look to the mentioned patches.
> 

I totally agree, but due to the dynamic nature described above I have a hard
time figuring out how to make it fit; hence this RFC.

> >  Documentation/devicetree/bindings/mfd/qcom-rpm.txt |   28 ++++++++
> >  drivers/regulator/qcom_rpm-regulator.c             |   68 +++++++++++++++-----
> 
> Against which tree this patch has been developed? afaict
> Documentation/devicetree/bindings/mfd/qcom-rpm.txt does not exist even
> in the latest for-next [3] branch of the mfd tree.
> 

v3.18-rc1 + https://lkml.org/lkml/2014/9/22/731

As I tried to explain in the cover letter, the DT bindings that I change here
are not acked and this RFC is an attempt to come to a conclusion in how to
design the sleep state part - which will change the bindings.

> >
> >         #include <dt-bindings/mfd/qcom-rpm.h>
> 
> This file doesn't exit either and the regulator driver depends on
> MFD_QCOM_RPM which also is not present in mainline.
> 
> By looking at the mail archives I see that you posted both the
> regulator and mfd driver in the same series [4] but only the regulator
> driver was picked by Mark so I guess Lee has to pick the mfd driver in
> order to allow the regulator driver to be built.
> 

Correct, I hope that after sorting the sleep state part out we can get some
acks on things.

Thanks for your review!

Regards,
Bjorn
diff mbox

Patch

diff --git a/Documentation/devicetree/bindings/mfd/qcom-rpm.txt b/Documentation/devicetree/bindings/mfd/qcom-rpm.txt
index 4264021..4671eef 100644
--- a/Documentation/devicetree/bindings/mfd/qcom-rpm.txt
+++ b/Documentation/devicetree/bindings/mfd/qcom-rpm.txt
@@ -112,6 +112,13 @@  of valid subnodes that can operate on these resources.
 	Definition: select that the power supply should operate in hysteretic
 		    mode, instead of the default pwm mode
 
+- qcom,rpm-assisted-disable:
+	Usage: optional
+	Value type: <empty>
+	Definition: select that the regulator is supplying the active CPU(s)
+		    and can only be disabled with the assistans from the RPM
+		    after going to sleep
+
 Standard regulator bindings are used inside switch mode power supply subnodes.
 Check Documentation/devicetree/bindings/regulator/regulator.txt for more
 details.
@@ -160,6 +167,13 @@  details.
 						qcom,rpm-pm8921-nldo,
 						qcom,rpm-pm8921-nldo1200
 
+- qcom,rpm-assisted-disable:
+	Usage: optional
+	Value type: <empty>
+	Definition: select that the regulator is supplying the active CPU(s)
+		    and can only be disabled with the assistans from the RPM
+		    after going to sleep
+
 Standard regulator bindings are used inside switch low-dropout regulator
 subnodes.  Check Documentation/devicetree/bindings/regulator/regulator.txt for
 more details.
@@ -190,6 +204,13 @@  more details.
 		    2740000, 2400000, 2130000, 1920000, 1750000, 1600000,
 		    1480000, 1370000, 1280000, 1200000
 
+- qcom,rpm-assisted-disable:
+	Usage: optional
+	Value type: <empty>
+	Definition: select that the regulator is supplying the active CPU(s)
+		    and can only be disabled with the assistans from the RPM
+		    after going to sleep
+
 Standard regulator bindings are used inside negative charge pump regulator
 subnodes.  Check Documentation/devicetree/bindings/regulator/regulator.txt for
 more details.
@@ -215,6 +236,13 @@  more details.
 		    QCOM_RPM_PM8921_LVS1 - QCOM_RPM_PM8921_LVS7,
 		    QCOM_RPM_PM8921_MVS
 
+- qcom,rpm-assisted-disable:
+	Usage: optional
+	Value type: <empty>
+	Definition: select that the regulator is supplying the active CPU(s)
+		    and can only be disabled with the assistans from the RPM
+		    after going to sleep
+
 = EXAMPLE
 
 	#include <dt-bindings/mfd/qcom-rpm.h>
diff --git a/drivers/regulator/qcom_rpm-regulator.c b/drivers/regulator/qcom_rpm-regulator.c
index 4fc1c7e..2a78f59 100644
--- a/drivers/regulator/qcom_rpm-regulator.c
+++ b/drivers/regulator/qcom_rpm-regulator.c
@@ -24,6 +24,7 @@ 
 #include <dt-bindings/mfd/qcom-rpm.h>
 
 #define MAX_REQUEST_LEN 2
+#define RPM_NUM_STATES	2
 
 struct request_member {
 	int		word;
@@ -61,13 +62,15 @@  struct qcom_rpm_reg {
 	const struct rpm_reg_parts *parts;
 
 	int resource;
-	u32 val[MAX_REQUEST_LEN];
+	u32 val[RPM_NUM_STATES][MAX_REQUEST_LEN];
 
 	int uV;
 	int is_enabled;
 
 	bool supports_force_mode_auto;
 	bool supports_force_mode_bypass;
+
+	bool rpm_assist;
 };
 
 static const struct rpm_reg_parts rpm8660_ldo_parts = {
@@ -188,19 +191,20 @@  static const struct regulator_linear_range ncp_ranges[] = {
 };
 
 static int rpm_reg_write(struct qcom_rpm_reg *vreg,
+			 int state,
 			 const struct request_member *req,
 			 const int value)
 {
 	if (WARN_ON((value << req->shift) & ~req->mask))
 		return -EINVAL;
 
-	vreg->val[req->word] &= ~req->mask;
-	vreg->val[req->word] |= value << req->shift;
+	vreg->val[state][req->word] &= ~req->mask;
+	vreg->val[state][req->word] |= value << req->shift;
 
 	return qcom_rpm_write(vreg->rpm,
-			      RPM_ACTIVE_STATE,
+			      state,
 			      vreg->resource,
-			      vreg->val,
+			      vreg->val[state],
 			      vreg->parts->request_len);
 }
 
@@ -222,8 +226,11 @@  static int rpm_reg_set_mV_sel(struct regulator_dev *rdev,
 
 	mutex_lock(&vreg->lock);
 	vreg->uV = uV;
-	if (vreg->is_enabled)
-		ret = rpm_reg_write(vreg, req, vreg->uV / 1000);
+	if (vreg->is_enabled) {
+		ret = rpm_reg_write(vreg, RPM_ACTIVE_STATE, req, vreg->uV / 1000);
+		if (!ret && vreg->rpm_assist)
+			ret = rpm_reg_write(vreg, RPM_SLEEP_STATE, req, vreg->uV / 1000);
+	}
 	mutex_unlock(&vreg->lock);
 
 	return ret;
@@ -247,8 +254,11 @@  static int rpm_reg_set_uV_sel(struct regulator_dev *rdev,
 
 	mutex_lock(&vreg->lock);
 	vreg->uV = uV;
-	if (vreg->is_enabled)
-		ret = rpm_reg_write(vreg, req, vreg->uV);
+	if (vreg->is_enabled) {
+		ret = rpm_reg_write(vreg, RPM_ACTIVE_STATE, req, vreg->uV);
+		if (!ret && vreg->rpm_assist)
+			ret = rpm_reg_write(vreg, RPM_SLEEP_STATE, req, vreg->uV);
+	}
 	mutex_unlock(&vreg->lock);
 
 	return ret;
@@ -266,13 +276,16 @@  static int rpm_reg_mV_enable(struct regulator_dev *rdev)
 	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
 	const struct rpm_reg_parts *parts = vreg->parts;
 	const struct request_member *req = &parts->mV;
+	int state;
 	int ret;
 
 	if (req->mask == 0)
 		return -EINVAL;
 
+	state = vreg->rpm_assist ? RPM_SLEEP_STATE : RPM_ACTIVE_STATE;
+
 	mutex_lock(&vreg->lock);
-	ret = rpm_reg_write(vreg, req, vreg->uV / 1000);
+	ret = rpm_reg_write(vreg, state, req, vreg->uV / 1000);
 	if (!ret)
 		vreg->is_enabled = 1;
 	mutex_unlock(&vreg->lock);
@@ -285,13 +298,16 @@  static int rpm_reg_uV_enable(struct regulator_dev *rdev)
 	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
 	const struct rpm_reg_parts *parts = vreg->parts;
 	const struct request_member *req = &parts->uV;
+	int state;
 	int ret;
 
 	if (req->mask == 0)
 		return -EINVAL;
 
+	state = vreg->rpm_assist ? RPM_SLEEP_STATE : RPM_ACTIVE_STATE;
+
 	mutex_lock(&vreg->lock);
-	ret = rpm_reg_write(vreg, req, vreg->uV);
+	ret = rpm_reg_write(vreg, state, req, vreg->uV);
 	if (!ret)
 		vreg->is_enabled = 1;
 	mutex_unlock(&vreg->lock);
@@ -304,13 +320,16 @@  static int rpm_reg_switch_enable(struct regulator_dev *rdev)
 	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
 	const struct rpm_reg_parts *parts = vreg->parts;
 	const struct request_member *req = &parts->enable_state;
+	int state;
 	int ret;
 
 	if (req->mask == 0)
 		return -EINVAL;
 
+	state = vreg->rpm_assist ? RPM_SLEEP_STATE : RPM_ACTIVE_STATE;
+
 	mutex_lock(&vreg->lock);
-	ret = rpm_reg_write(vreg, req, 1);
+	ret = rpm_reg_write(vreg, state, req, 1);
 	if (!ret)
 		vreg->is_enabled = 1;
 	mutex_unlock(&vreg->lock);
@@ -323,13 +342,16 @@  static int rpm_reg_mV_disable(struct regulator_dev *rdev)
 	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
 	const struct rpm_reg_parts *parts = vreg->parts;
 	const struct request_member *req = &parts->mV;
+	int state;
 	int ret;
 
 	if (req->mask == 0)
 		return -EINVAL;
 
+	state = vreg->rpm_assist ? RPM_SLEEP_STATE : RPM_ACTIVE_STATE;
+
 	mutex_lock(&vreg->lock);
-	ret = rpm_reg_write(vreg, req, 0);
+	ret = rpm_reg_write(vreg, state, req, 0);
 	if (!ret)
 		vreg->is_enabled = 0;
 	mutex_unlock(&vreg->lock);
@@ -342,13 +364,16 @@  static int rpm_reg_uV_disable(struct regulator_dev *rdev)
 	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
 	const struct rpm_reg_parts *parts = vreg->parts;
 	const struct request_member *req = &parts->uV;
+	int state;
 	int ret;
 
 	if (req->mask == 0)
 		return -EINVAL;
 
+	state = vreg->rpm_assist ? RPM_SLEEP_STATE : RPM_ACTIVE_STATE;
+
 	mutex_lock(&vreg->lock);
-	ret = rpm_reg_write(vreg, req, 0);
+	ret = rpm_reg_write(vreg, state, req, 0);
 	if (!ret)
 		vreg->is_enabled = 0;
 	mutex_unlock(&vreg->lock);
@@ -361,13 +386,16 @@  static int rpm_reg_switch_disable(struct regulator_dev *rdev)
 	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
 	const struct rpm_reg_parts *parts = vreg->parts;
 	const struct request_member *req = &parts->enable_state;
+	int state;
 	int ret;
 
 	if (req->mask == 0)
 		return -EINVAL;
 
+	state = vreg->rpm_assist ? RPM_SLEEP_STATE : RPM_ACTIVE_STATE;
+
 	mutex_lock(&vreg->lock);
-	ret = rpm_reg_write(vreg, req, 0);
+	ret = rpm_reg_write(vreg, state, req, 0);
 	if (!ret)
 		vreg->is_enabled = 0;
 	mutex_unlock(&vreg->lock);
@@ -590,8 +618,11 @@  static int rpm_reg_set(struct qcom_rpm_reg *vreg,
 	if (req->mask == 0 || (value << req->shift) & ~req->mask)
 		return -EINVAL;
 
-	vreg->val[req->word] &= ~req->mask;
-	vreg->val[req->word] |= value << req->shift;
+	vreg->val[RPM_ACTIVE_STATE][req->word] &= ~req->mask;
+	vreg->val[RPM_ACTIVE_STATE][req->word] |= value << req->shift;
+
+	vreg->val[RPM_SLEEP_STATE][req->word] &= ~req->mask;
+	vreg->val[RPM_SLEEP_STATE][req->word] |= value << req->shift;
 
 	return 0;
 }
@@ -690,6 +721,9 @@  static int rpm_reg_probe(struct platform_device *pdev)
 		}
 	}
 
+	key = "qcom,rpm-assisted-disable";
+	vreg->rpm_assist = of_property_read_bool(pdev->dev.of_node, key);
+
 	if (vreg->parts->freq.mask) {
 		ret = rpm_reg_of_parse_freq(&pdev->dev, vreg);
 		if (ret < 0)