diff mbox

[RFC,1/2] mfd: qcom-rpm: Expose sleep state resources to clients

Message ID 1415659966-16200-2-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
Resources exposed from the RPM have an "active state" that is used during
normal operations and a "sleep state" that is used for HW assisted sleep
modes. Expose this in the api to let client drivers set the "sleep
state" as well.

Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
---
 drivers/mfd/qcom_rpm.c                 |    9 +++++----
 drivers/regulator/qcom_rpm-regulator.c |    1 +
 include/linux/mfd/qcom_rpm.h           |    5 ++++-
 3 files changed, 10 insertions(+), 5 deletions(-)

Comments

Lee Jones Nov. 11, 2014, 12:04 p.m. UTC | #1
On Mon, 10 Nov 2014, Bjorn Andersson wrote:

> Resources exposed from the RPM have an "active state" that is used during
> normal operations and a "sleep state" that is used for HW assisted sleep
> modes. Expose this in the api to let client drivers set the "sleep
> state" as well.

I assume you have users lined up which will request a sleeping state?

> Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
> ---
>  drivers/mfd/qcom_rpm.c                 |    9 +++++----
>  drivers/regulator/qcom_rpm-regulator.c |    1 +
>  include/linux/mfd/qcom_rpm.h           |    5 ++++-
>  3 files changed, 10 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/mfd/qcom_rpm.c b/drivers/mfd/qcom_rpm.c
> index 0dd7a6fe..f696328 100644
> --- a/drivers/mfd/qcom_rpm.c
> +++ b/drivers/mfd/qcom_rpm.c
> @@ -67,7 +67,6 @@ struct qcom_rpm {
>  #define RPM_ACK_SELECTOR	23
>  #define RPM_SELECT_SIZE		7
>  
> -#define RPM_ACTIVE_STATE	BIT(0)
>  #define RPM_NOTIFICATION	BIT(30)
>  #define RPM_REJECTED		BIT(31)
>  
> @@ -332,7 +331,10 @@ static const struct of_device_id qcom_rpm_of_match[] = {
>  };
>  MODULE_DEVICE_TABLE(of, qcom_rpm_of_match);
>  
> -int qcom_rpm_write(struct qcom_rpm *rpm, int resource, u32 *buf, size_t count)
> +int qcom_rpm_write(struct qcom_rpm *rpm,
> +		   int state,
> +		   int resource,
> +		   u32 *buf, size_t count)
>  {
>  	const struct qcom_rpm_resource *res;
>  	const struct qcom_rpm_data *data = rpm->data;
> @@ -359,8 +361,7 @@ int qcom_rpm_write(struct qcom_rpm *rpm, int resource, u32 *buf, size_t count)
>  			       RPM_CTRL_REG(rpm, RPM_REQ_SELECT + i));
>  	}
>  
> -	writel_relaxed(RPM_ACTIVE_STATE,
> -		       RPM_CTRL_REG(rpm, RPM_REQUEST_CONTEXT));
> +	writel_relaxed(BIT(state), RPM_CTRL_REG(rpm, RPM_REQUEST_CONTEXT));

How are the state bits organised?

>  	reinit_completion(&rpm->ack);
>  	regmap_write(rpm->ipc_regmap, rpm->ipc_offset, BIT(rpm->ipc_bit));
> diff --git a/drivers/regulator/qcom_rpm-regulator.c b/drivers/regulator/qcom_rpm-regulator.c
> index b55cd5b..4fc1c7e 100644
> --- a/drivers/regulator/qcom_rpm-regulator.c
> +++ b/drivers/regulator/qcom_rpm-regulator.c
> @@ -198,6 +198,7 @@ static int rpm_reg_write(struct qcom_rpm_reg *vreg,
>  	vreg->val[req->word] |= value << req->shift;
>  
>  	return qcom_rpm_write(vreg->rpm,
> +			      RPM_ACTIVE_STATE,
>  			      vreg->resource,
>  			      vreg->val,
>  			      vreg->parts->request_len);
> diff --git a/include/linux/mfd/qcom_rpm.h b/include/linux/mfd/qcom_rpm.h
> index a60798d..f0e70b2 100644
> --- a/include/linux/mfd/qcom_rpm.h
> +++ b/include/linux/mfd/qcom_rpm.h
> @@ -5,6 +5,9 @@
>  
>  struct qcom_rpm;
>  
> -int qcom_rpm_write(struct qcom_rpm *rpm, int resource, u32 *buf, size_t count);
> +#define RPM_ACTIVE_STATE	0
> +#define RPM_SLEEP_STATE		1
> +
> +int qcom_rpm_write(struct qcom_rpm *rpm, int state, int resource, u32 *buf, size_t count);
>  
>  #endif
Bjorn Andersson Nov. 11, 2014, 6:33 p.m. UTC | #2
On Tue 11 Nov 04:04 PST 2014, Lee Jones wrote:

> On Mon, 10 Nov 2014, Bjorn Andersson wrote:
> 
> > Resources exposed from the RPM have an "active state" that is used during
> > normal operations and a "sleep state" that is used for HW assisted sleep
> > modes. Expose this in the api to let client drivers set the "sleep
> > state" as well.
> 
> I assume you have users lined up which will request a sleeping state?
> 

All users of this interface (regulators, clocks and bus scaling) will have to
be able to specify this.

[..]
> > @@ -359,8 +361,7 @@ int qcom_rpm_write(struct qcom_rpm *rpm, int resource, u32 *buf, size_t count)
> >  			       RPM_CTRL_REG(rpm, RPM_REQ_SELECT + i));
> >  	}
> >  
> > -	writel_relaxed(RPM_ACTIVE_STATE,
> > -		       RPM_CTRL_REG(rpm, RPM_REQUEST_CONTEXT));
> > +	writel_relaxed(BIT(state), RPM_CTRL_REG(rpm, RPM_REQUEST_CONTEXT));
> 
> How are the state bits organised?
> 

BIT(0) is active mode, BIT(1) is sleep mode, as specified below. I could add
some sanity checking here if you would like to.

[..]
> > diff --git a/include/linux/mfd/qcom_rpm.h b/include/linux/mfd/qcom_rpm.h
> > index a60798d..f0e70b2 100644
> > --- a/include/linux/mfd/qcom_rpm.h
> > +++ b/include/linux/mfd/qcom_rpm.h
> > +#define RPM_ACTIVE_STATE	0
> > +#define RPM_SLEEP_STATE		1

Regards,
Bjorn
Lee Jones Nov. 12, 2014, 9:52 a.m. UTC | #3
On Tue, 11 Nov 2014, Bjorn Andersson wrote:

> On Tue 11 Nov 04:04 PST 2014, Lee Jones wrote:
> 
> > On Mon, 10 Nov 2014, Bjorn Andersson wrote:
> > 
> > > Resources exposed from the RPM have an "active state" that is used during
> > > normal operations and a "sleep state" that is used for HW assisted sleep
> > > modes. Expose this in the api to let client drivers set the "sleep
> > > state" as well.
> > 
> > I assume you have users lined up which will request a sleeping state?
> > 
> 
> All users of this interface (regulators, clocks and bus scaling) will have to
> be able to specify this.
> 
> [..]
> > > @@ -359,8 +361,7 @@ int qcom_rpm_write(struct qcom_rpm *rpm, int resource, u32 *buf, size_t count)
> > >  			       RPM_CTRL_REG(rpm, RPM_REQ_SELECT + i));
> > >  	}
> > >  
> > > -	writel_relaxed(RPM_ACTIVE_STATE,
> > > -		       RPM_CTRL_REG(rpm, RPM_REQUEST_CONTEXT));
> > > +	writel_relaxed(BIT(state), RPM_CTRL_REG(rpm, RPM_REQUEST_CONTEXT));
> > 
> > How are the state bits organised?
> > 
> 
> BIT(0) is active mode, BIT(1) is sleep mode, as specified below. I could add
> some sanity checking here if you would like to.

I'm just double checking that you know what that means.

BIT(0) == b01
BIT(1) == b10

It seems strange to represent a single boolean state over 2 bits.

Also, what happens if b11 or b00 occurs?

> [..]
> > > diff --git a/include/linux/mfd/qcom_rpm.h b/include/linux/mfd/qcom_rpm.h
> > > index a60798d..f0e70b2 100644
> > > --- a/include/linux/mfd/qcom_rpm.h
> > > +++ b/include/linux/mfd/qcom_rpm.h
> > > +#define RPM_ACTIVE_STATE	0
> > > +#define RPM_SLEEP_STATE		1
> 
> Regards,
> Bjorn
Lina Iyer Nov. 12, 2014, 2:45 p.m. UTC | #4
On Wed, Nov 12 2014 at 02:52 -0700, Lee Jones wrote:
>On Tue, 11 Nov 2014, Bjorn Andersson wrote:
>
>> On Tue 11 Nov 04:04 PST 2014, Lee Jones wrote:
>>
>> > On Mon, 10 Nov 2014, Bjorn Andersson wrote:
>> >

> > > +	writel_relaxed(BIT(state), RPM_CTRL_REG(rpm, RPM_REQUEST_CONTEXT));
>> >
>> > How are the state bits organised?
>> >
>>
>> BIT(0) is active mode, BIT(1) is sleep mode, as specified below. I could add
>> some sanity checking here if you would like to.
>
>I'm just double checking that you know what that means.
>
>BIT(0) == b01
>BIT(1) == b10
>
>It seems strange to represent a single boolean state over 2 bits.
>
>Also, what happens if b11 or b00 occurs?
>
Lee is correct, it should be 0 for Active and 1 for Sleep set. 


Lina
Bjorn Andersson Nov. 12, 2014, 7:23 p.m. UTC | #5
On Wed 12 Nov 06:45 PST 2014, Lina Iyer wrote:

> On Wed, Nov 12 2014 at 02:52 -0700, Lee Jones wrote:
> >On Tue, 11 Nov 2014, Bjorn Andersson wrote:
> >
> >> On Tue 11 Nov 04:04 PST 2014, Lee Jones wrote:
> >>
> >> > On Mon, 10 Nov 2014, Bjorn Andersson wrote:
> >> >
> 
> > > > +	writel_relaxed(BIT(state), RPM_CTRL_REG(rpm, RPM_REQUEST_CONTEXT));
> >> >
> >> > How are the state bits organised?
> >> >
> >>
> >> BIT(0) is active mode, BIT(1) is sleep mode, as specified below. I could add
> >> some sanity checking here if you would like to.
> >
> >I'm just double checking that you know what that means.
> >
> >BIT(0) == b01
> >BIT(1) == b10
> >
> >It seems strange to represent a single boolean state over 2 bits.
> >
> >Also, what happens if b11 or b00 occurs?
> >
> Lee is correct, it should be 0 for Active and 1 for Sleep set. 
> 

In the caf msm-3.4 tree the regulator core will call e.g. vreg_set_voltage()
that will call vreg_set(), that will call msm_rpm_set(MSM_RPM_CTX_SET_0,...).
That comes from the following:

enum {
	MSM_RPM_CTX_SET_0,
	MSM_RPM_CTX_SET_SLEEP,
	MSM_RPM_CTX_SET_COUNT,

	MSM_RPM_CTX_NOTIFICATION = 30,
	MSM_RPM_CTX_REJECTED = 31,
};

So there's your 0 and 1.

msm_rpm_set() calls msm_rpm_set_common() that calls msm_rpm_set_exclusive()
that contains these two statements:

        uint32_t ctx_mask = msm_rpm_get_ctx_mask(ctx);
	...
	msm_rpm_write(MSM_RPM_PAGE_CTRL, target_ctrl(MSM_RPM_CTRL_REQ_CTX_0), ctx_mask);

And we have:

static inline uint32_t msm_rpm_get_ctx_mask(unsigned int ctx)
{
	return 1UL << ctx;
}

So, as far as I can see it should be BIT(state) here. But there's a lot of code
and a lot of indirections here and I've been tricked by it before, so please
let me know if I got something wrong on the way.

Regards,
Bjorn
Bjorn Andersson Nov. 12, 2014, 7:55 p.m. UTC | #6
On Wed 12 Nov 01:52 PST 2014, Lee Jones wrote:

> On Tue, 11 Nov 2014, Bjorn Andersson wrote:
> 
> > On Tue 11 Nov 04:04 PST 2014, Lee Jones wrote:
> > 
> > > On Mon, 10 Nov 2014, Bjorn Andersson wrote:
> > > 
> > > > Resources exposed from the RPM have an "active state" that is used during
> > > > normal operations and a "sleep state" that is used for HW assisted sleep
> > > > modes. Expose this in the api to let client drivers set the "sleep
> > > > state" as well.
> > > 
> > > I assume you have users lined up which will request a sleeping state?
> > > 
> > 
> > All users of this interface (regulators, clocks and bus scaling) will have to
> > be able to specify this.
> > 
> > [..]
> > > > @@ -359,8 +361,7 @@ int qcom_rpm_write(struct qcom_rpm *rpm, int resource, u32 *buf, size_t count)
> > > >  			       RPM_CTRL_REG(rpm, RPM_REQ_SELECT + i));
> > > >  	}
> > > >  
> > > > -	writel_relaxed(RPM_ACTIVE_STATE,
> > > > -		       RPM_CTRL_REG(rpm, RPM_REQUEST_CONTEXT));
> > > > +	writel_relaxed(BIT(state), RPM_CTRL_REG(rpm, RPM_REQUEST_CONTEXT));
> > > 
> > > How are the state bits organised?
> > > 
> > 
> > BIT(0) is active mode, BIT(1) is sleep mode, as specified below. I could add
> > some sanity checking here if you would like to.
> 
> I'm just double checking that you know what that means.
> 
> BIT(0) == b01
> BIT(1) == b10
> 
> It seems strange to represent a single boolean state over 2 bits.
> 

I'm aware of this and find most parts of this solution to be strange.

> Also, what happens if b11 or b00 occurs?
> 

Had to pull out the firmware for the other side; it boils down to a count of
trailing zeros, with 0 giving 0, that is then turned back into and enum where
ACTIVE is 0 and SLEEP is 1. This is then sanity checked to be less than 2.

So the possible values and results would be:
 00 => ACTIVE (seems invalid but "accidentally" accepted)
 01 => ACTIVE
 10 => SLEEP
 11 => ACTIVE

In one of the later versions of the RPM (not applicable for any of these
platforms) 2 seems to be a valid choice as well; but there it's passed as an
u32 and not a bitmask.

Regards,
Bjorn
Lina Iyer Nov. 19, 2014, 6:06 p.m. UTC | #7
On Wed, Nov 12 2014 at 12:23 -0700, Bjorn Andersson wrote:
>On Wed 12 Nov 06:45 PST 2014, Lina Iyer wrote:
>
>> On Wed, Nov 12 2014 at 02:52 -0700, Lee Jones wrote:
>> >On Tue, 11 Nov 2014, Bjorn Andersson wrote:
>> >
>> >> On Tue 11 Nov 04:04 PST 2014, Lee Jones wrote:
>> >>
>> >> > On Mon, 10 Nov 2014, Bjorn Andersson wrote:
>> >> >
>>
>> > > > +	writel_relaxed(BIT(state), RPM_CTRL_REG(rpm, RPM_REQUEST_CONTEXT));
>> >> >
>> >> > How are the state bits organised?
>> >> >
>> >>
>> >> BIT(0) is active mode, BIT(1) is sleep mode, as specified below. I could add
>> >> some sanity checking here if you would like to.
>> >
>> >I'm just double checking that you know what that means.
>> >
>> >BIT(0) == b01
>> >BIT(1) == b10
>> >
>> >It seems strange to represent a single boolean state over 2 bits.
>> >
>> >Also, what happens if b11 or b00 occurs?
>> >
>> Lee is correct, it should be 0 for Active and 1 for Sleep set.
>>
>
>In the caf msm-3.4 tree the regulator core will call e.g. vreg_set_voltage()
>that will call vreg_set(), that will call msm_rpm_set(MSM_RPM_CTX_SET_0,...).
>That comes from the following:
>
>enum {
>	MSM_RPM_CTX_SET_0,
>	MSM_RPM_CTX_SET_SLEEP,
>	MSM_RPM_CTX_SET_COUNT,
>
>	MSM_RPM_CTX_NOTIFICATION = 30,
>	MSM_RPM_CTX_REJECTED = 31,
>};
>
>So there's your 0 and 1.
>
>msm_rpm_set() calls msm_rpm_set_common() that calls msm_rpm_set_exclusive()
>that contains these two statements:
>
>        uint32_t ctx_mask = msm_rpm_get_ctx_mask(ctx);
>	...
>	msm_rpm_write(MSM_RPM_PAGE_CTRL, target_ctrl(MSM_RPM_CTRL_REQ_CTX_0), ctx_mask);
>
>And we have:
>
>static inline uint32_t msm_rpm_get_ctx_mask(unsigned int ctx)
>{
>	return 1UL << ctx;
>}
>
>So, as far as I can see it should be BIT(state) here. But there's a lot of code
>and a lot of indirections here and I've been tricked by it before, so please
>let me know if I got something wrong on the way.
Sorry, I retract my earlier objection. This is how it is, strangely.

>
>Regards,
>Bjorn
diff mbox

Patch

diff --git a/drivers/mfd/qcom_rpm.c b/drivers/mfd/qcom_rpm.c
index 0dd7a6fe..f696328 100644
--- a/drivers/mfd/qcom_rpm.c
+++ b/drivers/mfd/qcom_rpm.c
@@ -67,7 +67,6 @@  struct qcom_rpm {
 #define RPM_ACK_SELECTOR	23
 #define RPM_SELECT_SIZE		7
 
-#define RPM_ACTIVE_STATE	BIT(0)
 #define RPM_NOTIFICATION	BIT(30)
 #define RPM_REJECTED		BIT(31)
 
@@ -332,7 +331,10 @@  static const struct of_device_id qcom_rpm_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, qcom_rpm_of_match);
 
-int qcom_rpm_write(struct qcom_rpm *rpm, int resource, u32 *buf, size_t count)
+int qcom_rpm_write(struct qcom_rpm *rpm,
+		   int state,
+		   int resource,
+		   u32 *buf, size_t count)
 {
 	const struct qcom_rpm_resource *res;
 	const struct qcom_rpm_data *data = rpm->data;
@@ -359,8 +361,7 @@  int qcom_rpm_write(struct qcom_rpm *rpm, int resource, u32 *buf, size_t count)
 			       RPM_CTRL_REG(rpm, RPM_REQ_SELECT + i));
 	}
 
-	writel_relaxed(RPM_ACTIVE_STATE,
-		       RPM_CTRL_REG(rpm, RPM_REQUEST_CONTEXT));
+	writel_relaxed(BIT(state), RPM_CTRL_REG(rpm, RPM_REQUEST_CONTEXT));
 
 	reinit_completion(&rpm->ack);
 	regmap_write(rpm->ipc_regmap, rpm->ipc_offset, BIT(rpm->ipc_bit));
diff --git a/drivers/regulator/qcom_rpm-regulator.c b/drivers/regulator/qcom_rpm-regulator.c
index b55cd5b..4fc1c7e 100644
--- a/drivers/regulator/qcom_rpm-regulator.c
+++ b/drivers/regulator/qcom_rpm-regulator.c
@@ -198,6 +198,7 @@  static int rpm_reg_write(struct qcom_rpm_reg *vreg,
 	vreg->val[req->word] |= value << req->shift;
 
 	return qcom_rpm_write(vreg->rpm,
+			      RPM_ACTIVE_STATE,
 			      vreg->resource,
 			      vreg->val,
 			      vreg->parts->request_len);
diff --git a/include/linux/mfd/qcom_rpm.h b/include/linux/mfd/qcom_rpm.h
index a60798d..f0e70b2 100644
--- a/include/linux/mfd/qcom_rpm.h
+++ b/include/linux/mfd/qcom_rpm.h
@@ -5,6 +5,9 @@ 
 
 struct qcom_rpm;
 
-int qcom_rpm_write(struct qcom_rpm *rpm, int resource, u32 *buf, size_t count);
+#define RPM_ACTIVE_STATE	0
+#define RPM_SLEEP_STATE		1
+
+int qcom_rpm_write(struct qcom_rpm *rpm, int state, int resource, u32 *buf, size_t count);
 
 #endif