Linux-ARM-MSM Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps
@ 2020-04-01 17:50 Loic Poulain
  2020-04-01 23:46 ` Bjorn Andersson
                   ` (2 more replies)
  0 siblings, 3 replies; 32+ messages in thread
From: Loic Poulain @ 2020-04-01 17:50 UTC (permalink / raw)
  To: bjorn.andersson, agross; +Cc: linux-arm-msm, Loic Poulain

The highest cpu frequency opps have been dropped because CPR is not
supported. However, we can simply specify operating voltage so that
they match the max corner voltages for each freq. With that, we can
support up to 1.36Ghz. Ideally, msm8916 CPR should be implemented to
fine tune operating voltages and optimize power consumption.

This patch:
- Adds missing opps and corresponding target voltages to msm8916.dtsi.
- Adds cpu-supply to apq8016-sbc.dtsi (board level info).
- Adds pm8916 spmi regulator node to pm8916.dtsi.

Tested with a dragonboard-410c.

Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
---
 arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi | 24 ++++++++++++++++++++++++
 arch/arm64/boot/dts/qcom/msm8916.dtsi     | 24 ++++++++++++++++++++++++
 arch/arm64/boot/dts/qcom/pm8916.dtsi      |  6 ++++++
 3 files changed, 54 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
index 037e26b..f1c1216 100644
--- a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
@@ -560,6 +560,30 @@
 	qcom,mbhc-vthreshold-high = <75 150 237 450 500>;
 };
 
+&spm_regulators {
+	vdd_cpu: s2 {
+		regulator-always-on;
+		regulator-min-microvolt = <1050000>;
+		regulator-max-microvolt = <1350000>;
+	};
+};
+
+&CPU0 {
+	cpu-supply = <&vdd_cpu>;
+};
+
+&CPU1 {
+	cpu-supply = <&vdd_cpu>;
+};
+
+&CPU2 {
+	cpu-supply = <&vdd_cpu>;
+};
+
+&CPU3 {
+	cpu-supply = <&vdd_cpu>;
+};
+
 &smd_rpm_regulators {
 	vdd_l1_l2_l3-supply = <&pm8916_s3>;
 	vdd_l5-supply = <&pm8916_s3>;
diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
index 9f31064..9805af0 100644
--- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
@@ -342,15 +342,39 @@
 
 		opp-200000000 {
 			opp-hz = /bits/ 64 <200000000>;
+			opp-microvolt = <1050000>;
 		};
 		opp-400000000 {
 			opp-hz = /bits/ 64 <400000000>;
+			opp-microvolt = <1050000>;
+		};
+		opp-533330000 {
+			opp-hz = /bits/ 64 <533330000>;
+			opp-microvolt = <1150000>;
 		};
 		opp-800000000 {
 			opp-hz = /bits/ 64 <800000000>;
+			opp-microvolt = <1150000>;
 		};
 		opp-998400000 {
 			opp-hz = /bits/ 64 <998400000>;
+			opp-microvolt = <1350000>;
+		};
+		opp-1094400000 {
+			opp-hz = /bits/ 64 <1094400000>;
+			opp-microvolt = <1350000>;
+		};
+		opp-1152000000 {
+			opp-hz = /bits/ 64 <1152000000>;
+			opp-microvolt = <1350000>;
+		};
+		opp-1209600000 {
+			opp-hz = /bits/ 64 <1209600000>;
+			opp-microvolt = <1350000>;
+		};
+		opp-1363200000 {
+			opp-hz = /bits/ 64 <1363200000>;
+			opp-microvolt = <1350000>;
 		};
 	};
 
diff --git a/arch/arm64/boot/dts/qcom/pm8916.dtsi b/arch/arm64/boot/dts/qcom/pm8916.dtsi
index 0bcdf04..c9b9c4f 100644
--- a/arch/arm64/boot/dts/qcom/pm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8916.dtsi
@@ -157,5 +157,11 @@
 			vdd-micbias-supply = <&pm8916_l13>;
 			#sound-dai-cells = <1>;
 		};
+
+		spm_regulators: spm_regulators  {
+			compatible = "qcom,pm8916-regulators";
+			#address-cells = <1>;
+			#size-cells = <1>;
+		};
 	};
 };
-- 
2.7.4


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps
  2020-04-01 17:50 [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps Loic Poulain
@ 2020-04-01 23:46 ` Bjorn Andersson
  2020-04-02  8:13 ` Stephan Gerhold
  2020-04-28 20:04 ` Amit Kucheria
  2 siblings, 0 replies; 32+ messages in thread
From: Bjorn Andersson @ 2020-04-01 23:46 UTC (permalink / raw)
  To: Loic Poulain; +Cc: agross, linux-arm-msm

On Wed 01 Apr 10:50 PDT 2020, Loic Poulain wrote:

> The highest cpu frequency opps have been dropped because CPR is not
> supported. However, we can simply specify operating voltage so that
> they match the max corner voltages for each freq. With that, we can
> support up to 1.36Ghz. Ideally, msm8916 CPR should be implemented to
> fine tune operating voltages and optimize power consumption.
> 
> This patch:
> - Adds missing opps and corresponding target voltages to msm8916.dtsi.
> - Adds cpu-supply to apq8016-sbc.dtsi (board level info).
> - Adds pm8916 spmi regulator node to pm8916.dtsi.
> 
> Tested with a dragonboard-410c.
> 

Thanks Loic, happy to see you tying up these loose ends! Just one minor
nit below.

> Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
> ---
>  arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi | 24 ++++++++++++++++++++++++
>  arch/arm64/boot/dts/qcom/msm8916.dtsi     | 24 ++++++++++++++++++++++++
>  arch/arm64/boot/dts/qcom/pm8916.dtsi      |  6 ++++++
>  3 files changed, 54 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
> index 037e26b..f1c1216 100644
> --- a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
> +++ b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
> @@ -560,6 +560,30 @@
>  	qcom,mbhc-vthreshold-high = <75 150 237 450 500>;
>  };
>  
> +&spm_regulators {
> +	vdd_cpu: s2 {
> +		regulator-always-on;
> +		regulator-min-microvolt = <1050000>;
> +		regulator-max-microvolt = <1350000>;
> +	};
> +};
> +
> +&CPU0 {
> +	cpu-supply = <&vdd_cpu>;
> +};
> +
> +&CPU1 {
> +	cpu-supply = <&vdd_cpu>;
> +};
> +
> +&CPU2 {
> +	cpu-supply = <&vdd_cpu>;
> +};
> +
> +&CPU3 {
> +	cpu-supply = <&vdd_cpu>;
> +};
> +
>  &smd_rpm_regulators {
>  	vdd_l1_l2_l3-supply = <&pm8916_s3>;
>  	vdd_l5-supply = <&pm8916_s3>;
> diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> index 9f31064..9805af0 100644
> --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
> +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> @@ -342,15 +342,39 @@
>  
>  		opp-200000000 {
>  			opp-hz = /bits/ 64 <200000000>;
> +			opp-microvolt = <1050000>;
>  		};
>  		opp-400000000 {
>  			opp-hz = /bits/ 64 <400000000>;
> +			opp-microvolt = <1050000>;
> +		};
> +		opp-533330000 {
> +			opp-hz = /bits/ 64 <533330000>;
> +			opp-microvolt = <1150000>;
>  		};
>  		opp-800000000 {
>  			opp-hz = /bits/ 64 <800000000>;
> +			opp-microvolt = <1150000>;
>  		};
>  		opp-998400000 {
>  			opp-hz = /bits/ 64 <998400000>;
> +			opp-microvolt = <1350000>;
> +		};
> +		opp-1094400000 {
> +			opp-hz = /bits/ 64 <1094400000>;
> +			opp-microvolt = <1350000>;
> +		};
> +		opp-1152000000 {
> +			opp-hz = /bits/ 64 <1152000000>;
> +			opp-microvolt = <1350000>;
> +		};
> +		opp-1209600000 {
> +			opp-hz = /bits/ 64 <1209600000>;
> +			opp-microvolt = <1350000>;
> +		};
> +		opp-1363200000 {
> +			opp-hz = /bits/ 64 <1363200000>;
> +			opp-microvolt = <1350000>;
>  		};
>  	};
>  
> diff --git a/arch/arm64/boot/dts/qcom/pm8916.dtsi b/arch/arm64/boot/dts/qcom/pm8916.dtsi
> index 0bcdf04..c9b9c4f 100644
> --- a/arch/arm64/boot/dts/qcom/pm8916.dtsi
> +++ b/arch/arm64/boot/dts/qcom/pm8916.dtsi
> @@ -157,5 +157,11 @@
>  			vdd-micbias-supply = <&pm8916_l13>;
>  			#sound-dai-cells = <1>;
>  		};
> +
> +		spm_regulators: spm_regulators  {

There is the SPM regulator interface in the CPU subsystem, which is used
for hardware assisted entering and exiting of low power modes. And then
there's the direct PMIC control over SPMI. Except for the fact that the
SPM hardware uses SPMI for controlling the PMIC these are two different
things, and this is the SPMI one.

So the label, and node should be
		spmi_regulators: regulators {


Regards,
Bjorn

> +			compatible = "qcom,pm8916-regulators";
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +		};
>  	};
>  };
> -- 
> 2.7.4
> 

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps
  2020-04-01 17:50 [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps Loic Poulain
  2020-04-01 23:46 ` Bjorn Andersson
@ 2020-04-02  8:13 ` Stephan Gerhold
  2020-04-02  9:58   ` Loic Poulain
  2020-04-03  1:31   ` Bjorn Andersson
  2020-04-28 20:04 ` Amit Kucheria
  2 siblings, 2 replies; 32+ messages in thread
From: Stephan Gerhold @ 2020-04-02  8:13 UTC (permalink / raw)
  To: Loic Poulain; +Cc: bjorn.andersson, agross, linux-arm-msm, Niklas Cassel

Hi,

On Wed, Apr 01, 2020 at 07:50:59PM +0200, Loic Poulain wrote:
> The highest cpu frequency opps have been dropped because CPR is not
> supported. However, we can simply specify operating voltage so that
> they match the max corner voltages for each freq. With that, we can
> support up to 1.36Ghz. Ideally, msm8916 CPR should be implemented to
> fine tune operating voltages and optimize power consumption.

Thanks for the patch! I was wondering how to enable the higher CPU
frequencies for a while now...

I was actually quite excited to see CPR being mainlined for QCS404.
If we are trying to add such a workaround (rather than CPR) for MSM8916
now, does that mean it's unlikely to see CPR working for MSM8916
anytime soon?

AFAICT, there is a WIP branch from Niklas Cassel here:
https://git.linaro.org/people/nicolas.dechesne/niklas.cassel/kernel.git/log/?h=cpr-msm8916-mainline
but it hasn't been updated for a while. (Not sure if it was working
already...)

Can someone explain what is missing to make CPR work for MSM8916?

One other minor comment/question below.

> 
> This patch:
> - Adds missing opps and corresponding target voltages to msm8916.dtsi.
> - Adds cpu-supply to apq8016-sbc.dtsi (board level info).
> - Adds pm8916 spmi regulator node to pm8916.dtsi.
> 
> Tested with a dragonboard-410c.
> 
> Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
> ---
>  arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi | 24 ++++++++++++++++++++++++
>  arch/arm64/boot/dts/qcom/msm8916.dtsi     | 24 ++++++++++++++++++++++++
>  arch/arm64/boot/dts/qcom/pm8916.dtsi      |  6 ++++++
>  3 files changed, 54 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
> index 037e26b..f1c1216 100644
> --- a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
> +++ b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
> @@ -560,6 +560,30 @@
>  	qcom,mbhc-vthreshold-high = <75 150 237 450 500>;
>  };
>  
> +&spm_regulators {
> +	vdd_cpu: s2 {
> +		regulator-always-on;
> +		regulator-min-microvolt = <1050000>;
> +		regulator-max-microvolt = <1350000>;
> +	};
> +};
> +
> +&CPU0 {
> +	cpu-supply = <&vdd_cpu>;
> +};
> +
> +&CPU1 {
> +	cpu-supply = <&vdd_cpu>;
> +};
> +
> +&CPU2 {
> +	cpu-supply = <&vdd_cpu>;
> +};
> +
> +&CPU3 {
> +	cpu-supply = <&vdd_cpu>;
> +};
> +

I'm a bit confused about the separation here. The cpu-supply is defined
in the board-specific device tree, yet the voltages are set in the
common device tree below.

Is it even possible that the CPU is supplied by something other than S2
and if yes, how likely is this?

I'm asking because I have two other MSM8916 devices in mainline
(and a few more pending upstreaming), and it seems like I would need to
duplicate this into each of them.

Thanks,
Stephan

>  &smd_rpm_regulators {
>  	vdd_l1_l2_l3-supply = <&pm8916_s3>;
>  	vdd_l5-supply = <&pm8916_s3>;
> diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> index 9f31064..9805af0 100644
> --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
> +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> @@ -342,15 +342,39 @@
>  
>  		opp-200000000 {
>  			opp-hz = /bits/ 64 <200000000>;
> +			opp-microvolt = <1050000>;
>  		};
>  		opp-400000000 {
>  			opp-hz = /bits/ 64 <400000000>;
> +			opp-microvolt = <1050000>;
> +		};
> +		opp-533330000 {
> +			opp-hz = /bits/ 64 <533330000>;
> +			opp-microvolt = <1150000>;
>  		};
>  		opp-800000000 {
>  			opp-hz = /bits/ 64 <800000000>;
> +			opp-microvolt = <1150000>;
>  		};
>  		opp-998400000 {
>  			opp-hz = /bits/ 64 <998400000>;
> +			opp-microvolt = <1350000>;
> +		};
> +		opp-1094400000 {
> +			opp-hz = /bits/ 64 <1094400000>;
> +			opp-microvolt = <1350000>;
> +		};
> +		opp-1152000000 {
> +			opp-hz = /bits/ 64 <1152000000>;
> +			opp-microvolt = <1350000>;
> +		};
> +		opp-1209600000 {
> +			opp-hz = /bits/ 64 <1209600000>;
> +			opp-microvolt = <1350000>;
> +		};
> +		opp-1363200000 {
> +			opp-hz = /bits/ 64 <1363200000>;
> +			opp-microvolt = <1350000>;
>  		};
>  	};
>  
> diff --git a/arch/arm64/boot/dts/qcom/pm8916.dtsi b/arch/arm64/boot/dts/qcom/pm8916.dtsi
> index 0bcdf04..c9b9c4f 100644
> --- a/arch/arm64/boot/dts/qcom/pm8916.dtsi
> +++ b/arch/arm64/boot/dts/qcom/pm8916.dtsi
> @@ -157,5 +157,11 @@
>  			vdd-micbias-supply = <&pm8916_l13>;
>  			#sound-dai-cells = <1>;
>  		};
> +
> +		spm_regulators: spm_regulators  {
> +			compatible = "qcom,pm8916-regulators";
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +		};
>  	};
>  };
> -- 
> 2.7.4
> 

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps
  2020-04-02  8:13 ` Stephan Gerhold
@ 2020-04-02  9:58   ` Loic Poulain
  2020-04-03  1:31   ` Bjorn Andersson
  1 sibling, 0 replies; 32+ messages in thread
From: Loic Poulain @ 2020-04-02  9:58 UTC (permalink / raw)
  To: Stephan Gerhold; +Cc: Bjorn Andersson, Andy Gross, linux-arm-msm, Niklas Cassel

Hi Stephan,

On Thu, 2 Apr 2020 at 10:14, Stephan Gerhold <stephan@gerhold.net> wrote:
>
> Hi,
>
> On Wed, Apr 01, 2020 at 07:50:59PM +0200, Loic Poulain wrote:
> > The highest cpu frequency opps have been dropped because CPR is not
> > supported. However, we can simply specify operating voltage so that
> > they match the max corner voltages for each freq. With that, we can
> > support up to 1.36Ghz. Ideally, msm8916 CPR should be implemented to
> > fine tune operating voltages and optimize power consumption.
>
> Thanks for the patch! I was wondering how to enable the higher CPU
> frequencies for a while now...
>
> I was actually quite excited to see CPR being mainlined for QCS404.
> If we are trying to add such a workaround (rather than CPR) for MSM8916
> now, does that mean it's unlikely to see CPR working for MSM8916
> anytime soon?
>
> AFAICT, there is a WIP branch from Niklas Cassel here:
> https://git.linaro.org/people/nicolas.dechesne/niklas.cassel/kernel.git/log/?h=cpr-msm8916-mainline
> but it hasn't been updated for a while. (Not sure if it was working
> already...)
>
> Can someone explain what is missing to make CPR work for MSM8916?

Support should be relatively straightforward to add, but would request
some time to implement and validate.
This patch can be considered as a first step, using the ceiling voltages.

>
> One other minor comment/question below.
>
> >
> > This patch:
> > - Adds missing opps and corresponding target voltages to msm8916.dtsi.
> > - Adds cpu-supply to apq8016-sbc.dtsi (board level info).
> > - Adds pm8916 spmi regulator node to pm8916.dtsi.
> >
> > Tested with a dragonboard-410c.
> >
> > Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
> > ---
> >  arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi | 24 ++++++++++++++++++++++++
> >  arch/arm64/boot/dts/qcom/msm8916.dtsi     | 24 ++++++++++++++++++++++++
> >  arch/arm64/boot/dts/qcom/pm8916.dtsi      |  6 ++++++
> >  3 files changed, 54 insertions(+)
> >
> > diff --git a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
> > index 037e26b..f1c1216 100644
> > --- a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
> > +++ b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
> > @@ -560,6 +560,30 @@
> >       qcom,mbhc-vthreshold-high = <75 150 237 450 500>;
> >  };
> >
> > +&spm_regulators {
> > +     vdd_cpu: s2 {
> > +             regulator-always-on;
> > +             regulator-min-microvolt = <1050000>;
> > +             regulator-max-microvolt = <1350000>;
> > +     };
> > +};
> > +
> > +&CPU0 {
> > +     cpu-supply = <&vdd_cpu>;
> > +};
> > +
> > +&CPU1 {
> > +     cpu-supply = <&vdd_cpu>;
> > +};
> > +
> > +&CPU2 {
> > +     cpu-supply = <&vdd_cpu>;
> > +};
> > +
> > +&CPU3 {
> > +     cpu-supply = <&vdd_cpu>;
> > +};
> > +
>
> I'm a bit confused about the separation here. The cpu-supply is defined
> in the board-specific device tree, yet the voltages are set in the
> common device tree below.
>
> Is it even possible that the CPU is supplied by something other than S2
> and if yes, how likely is this?

Well nothing prevents to use a different PMIC, but you're right in
practice msm8916 is tightly coupled to pm8916 and s2 is clearly
specified as application processor regulator in pm8916 spec. So I'll
move that into msm8916 for the v2.

> I'm asking because I have two other MSM8916 devices in mainline
> (and a few more pending upstreaming), and it seems like I would need to
> duplicate this into each of them.

Would you be able to test and ack the V2 with these boards?

Regards,
Loic

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps
  2020-04-02  8:13 ` Stephan Gerhold
  2020-04-02  9:58   ` Loic Poulain
@ 2020-04-03  1:31   ` Bjorn Andersson
  2020-04-03 10:09     ` Stephan Gerhold
  1 sibling, 1 reply; 32+ messages in thread
From: Bjorn Andersson @ 2020-04-03  1:31 UTC (permalink / raw)
  To: Stephan Gerhold; +Cc: Loic Poulain, agross, linux-arm-msm

On Thu 02 Apr 01:13 PDT 2020, Stephan Gerhold wrote:

> Hi,
> 
> On Wed, Apr 01, 2020 at 07:50:59PM +0200, Loic Poulain wrote:
> > The highest cpu frequency opps have been dropped because CPR is not
> > supported. However, we can simply specify operating voltage so that
> > they match the max corner voltages for each freq. With that, we can
> > support up to 1.36Ghz. Ideally, msm8916 CPR should be implemented to
> > fine tune operating voltages and optimize power consumption.
> 
> Thanks for the patch! I was wondering how to enable the higher CPU
> frequencies for a while now...
> 
> I was actually quite excited to see CPR being mainlined for QCS404.
> If we are trying to add such a workaround (rather than CPR) for MSM8916
> now, does that mean it's unlikely to see CPR working for MSM8916
> anytime soon?
> 
> AFAICT, there is a WIP branch from Niklas Cassel here:
> https://git.linaro.org/people/nicolas.dechesne/niklas.cassel/kernel.git/log/?h=cpr-msm8916-mainline
> but it hasn't been updated for a while. (Not sure if it was working
> already...)
> 
> Can someone explain what is missing to make CPR work for MSM8916?
> 

CPR needs to control 3 things; VDD_APC, VDD_MX and MEMACC. On QCS404 it
seems we don't have to adjust VDD_MX, so the code for this is missing
from the driver.

So, afaict, what's missing is that rpmpd.c needs to gain support for
8916, then the CPR driver needs to gain a cpr_acc_desc and compatible
for 8916, it needs to reference the VDDMX power domain and before/after
we're adjusting the corner of the CPR we need to adjust the MX according
to the mapping specified in the downstream kernel (i.e.  1->4, 2->5 and
3->7).


Unfortunately, the requirement that VDDMX (VDD_MEM I presume) must be
higher than VDD_APC most likely needs to be taken into consideration for
Loic's proposed static voltage scaling as well. Unless VDD_MEM is left
in Turbo mode from the boot loader I think we need to take VDDMX to
corner 7 for speeds 998MHz and above (i.e. where we pull VDD_APC to
1.35V).

Regards,
Bjorn

> One other minor comment/question below.
> 
> > 
> > This patch:
> > - Adds missing opps and corresponding target voltages to msm8916.dtsi.
> > - Adds cpu-supply to apq8016-sbc.dtsi (board level info).
> > - Adds pm8916 spmi regulator node to pm8916.dtsi.
> > 
> > Tested with a dragonboard-410c.
> > 
> > Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
> > ---
> >  arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi | 24 ++++++++++++++++++++++++
> >  arch/arm64/boot/dts/qcom/msm8916.dtsi     | 24 ++++++++++++++++++++++++
> >  arch/arm64/boot/dts/qcom/pm8916.dtsi      |  6 ++++++
> >  3 files changed, 54 insertions(+)
> > 
> > diff --git a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
> > index 037e26b..f1c1216 100644
> > --- a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
> > +++ b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
> > @@ -560,6 +560,30 @@
> >  	qcom,mbhc-vthreshold-high = <75 150 237 450 500>;
> >  };
> >  
> > +&spm_regulators {
> > +	vdd_cpu: s2 {
> > +		regulator-always-on;
> > +		regulator-min-microvolt = <1050000>;
> > +		regulator-max-microvolt = <1350000>;
> > +	};
> > +};
> > +
> > +&CPU0 {
> > +	cpu-supply = <&vdd_cpu>;
> > +};
> > +
> > +&CPU1 {
> > +	cpu-supply = <&vdd_cpu>;
> > +};
> > +
> > +&CPU2 {
> > +	cpu-supply = <&vdd_cpu>;
> > +};
> > +
> > +&CPU3 {
> > +	cpu-supply = <&vdd_cpu>;
> > +};
> > +
> 
> I'm a bit confused about the separation here. The cpu-supply is defined
> in the board-specific device tree, yet the voltages are set in the
> common device tree below.
> 
> Is it even possible that the CPU is supplied by something other than S2
> and if yes, how likely is this?
> 
> I'm asking because I have two other MSM8916 devices in mainline
> (and a few more pending upstreaming), and it seems like I would need to
> duplicate this into each of them.
> 
> Thanks,
> Stephan
> 
> >  &smd_rpm_regulators {
> >  	vdd_l1_l2_l3-supply = <&pm8916_s3>;
> >  	vdd_l5-supply = <&pm8916_s3>;
> > diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > index 9f31064..9805af0 100644
> > --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > @@ -342,15 +342,39 @@
> >  
> >  		opp-200000000 {
> >  			opp-hz = /bits/ 64 <200000000>;
> > +			opp-microvolt = <1050000>;
> >  		};
> >  		opp-400000000 {
> >  			opp-hz = /bits/ 64 <400000000>;
> > +			opp-microvolt = <1050000>;
> > +		};
> > +		opp-533330000 {
> > +			opp-hz = /bits/ 64 <533330000>;
> > +			opp-microvolt = <1150000>;
> >  		};
> >  		opp-800000000 {
> >  			opp-hz = /bits/ 64 <800000000>;
> > +			opp-microvolt = <1150000>;
> >  		};
> >  		opp-998400000 {
> >  			opp-hz = /bits/ 64 <998400000>;
> > +			opp-microvolt = <1350000>;
> > +		};
> > +		opp-1094400000 {
> > +			opp-hz = /bits/ 64 <1094400000>;
> > +			opp-microvolt = <1350000>;
> > +		};
> > +		opp-1152000000 {
> > +			opp-hz = /bits/ 64 <1152000000>;
> > +			opp-microvolt = <1350000>;
> > +		};
> > +		opp-1209600000 {
> > +			opp-hz = /bits/ 64 <1209600000>;
> > +			opp-microvolt = <1350000>;
> > +		};
> > +		opp-1363200000 {
> > +			opp-hz = /bits/ 64 <1363200000>;
> > +			opp-microvolt = <1350000>;
> >  		};
> >  	};
> >  
> > diff --git a/arch/arm64/boot/dts/qcom/pm8916.dtsi b/arch/arm64/boot/dts/qcom/pm8916.dtsi
> > index 0bcdf04..c9b9c4f 100644
> > --- a/arch/arm64/boot/dts/qcom/pm8916.dtsi
> > +++ b/arch/arm64/boot/dts/qcom/pm8916.dtsi
> > @@ -157,5 +157,11 @@
> >  			vdd-micbias-supply = <&pm8916_l13>;
> >  			#sound-dai-cells = <1>;
> >  		};
> > +
> > +		spm_regulators: spm_regulators  {
> > +			compatible = "qcom,pm8916-regulators";
> > +			#address-cells = <1>;
> > +			#size-cells = <1>;
> > +		};
> >  	};
> >  };
> > -- 
> > 2.7.4
> > 

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps
  2020-04-03  1:31   ` Bjorn Andersson
@ 2020-04-03 10:09     ` Stephan Gerhold
  2020-04-03 18:00       ` Stephan Gerhold
  0 siblings, 1 reply; 32+ messages in thread
From: Stephan Gerhold @ 2020-04-03 10:09 UTC (permalink / raw)
  To: Bjorn Andersson; +Cc: Loic Poulain, agross, linux-arm-msm

On Thu, Apr 02, 2020 at 06:31:19PM -0700, Bjorn Andersson wrote:
> On Thu 02 Apr 01:13 PDT 2020, Stephan Gerhold wrote:
> 
> > Hi,
> > 
> > On Wed, Apr 01, 2020 at 07:50:59PM +0200, Loic Poulain wrote:
> > > The highest cpu frequency opps have been dropped because CPR is not
> > > supported. However, we can simply specify operating voltage so that
> > > they match the max corner voltages for each freq. With that, we can
> > > support up to 1.36Ghz. Ideally, msm8916 CPR should be implemented to
> > > fine tune operating voltages and optimize power consumption.
> > 
> > Thanks for the patch! I was wondering how to enable the higher CPU
> > frequencies for a while now...
> > 
> > I was actually quite excited to see CPR being mainlined for QCS404.
> > If we are trying to add such a workaround (rather than CPR) for MSM8916
> > now, does that mean it's unlikely to see CPR working for MSM8916
> > anytime soon?
> > 
> > AFAICT, there is a WIP branch from Niklas Cassel here:
> > https://git.linaro.org/people/nicolas.dechesne/niklas.cassel/kernel.git/log/?h=cpr-msm8916-mainline
> > but it hasn't been updated for a while. (Not sure if it was working
> > already...)
> > 
> > Can someone explain what is missing to make CPR work for MSM8916?
> > 
> 
> CPR needs to control 3 things; VDD_APC, VDD_MX and MEMACC. On QCS404 it
> seems we don't have to adjust VDD_MX, so the code for this is missing
> from the driver.
> 
> So, afaict, what's missing is that rpmpd.c needs to gain support for
> 8916, then the CPR driver needs to gain a cpr_acc_desc and compatible
> for 8916, it needs to reference the VDDMX power domain and before/after
> we're adjusting the corner of the CPR we need to adjust the MX according
> to the mapping specified in the downstream kernel (i.e.  1->4, 2->5 and
> 3->7).
> 
> 
> Unfortunately, the requirement that VDDMX (VDD_MEM I presume) must be
> higher than VDD_APC most likely needs to be taken into consideration for
> Loic's proposed static voltage scaling as well. Unless VDD_MEM is left
> in Turbo mode from the boot loader I think we need to take VDDMX to
> corner 7 for speeds 998MHz and above (i.e. where we pull VDD_APC to
> 1.35V).
> 

I see! I wonder how hard it would be to add MSM8916 to rpmpd,
looking at previous commits it's mainly setting up a few defines?

If I understand it correctly, the OPPs from rpmpd could then be
referenced as "required-opps" in the CPU OPP table so that VDD_MX is
scaled together with the CPU frequency, and doesn't need to stay at
turbo mode (like in v3 from Loic) the whole time.

Scaling VDD_APC and VDD_MEM to the maximum necessary for the selected
CPU frequency sounds like a good (temporary) solution to me until we
have full CPR eventually at some point.

Thanks,
Stephan

> > One other minor comment/question below.
> > 
> > > 
> > > This patch:
> > > - Adds missing opps and corresponding target voltages to msm8916.dtsi.
> > > - Adds cpu-supply to apq8016-sbc.dtsi (board level info).
> > > - Adds pm8916 spmi regulator node to pm8916.dtsi.
> > > 
> > > Tested with a dragonboard-410c.
> > > 
> > > Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
> > > ---
> > >  arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi | 24 ++++++++++++++++++++++++
> > >  arch/arm64/boot/dts/qcom/msm8916.dtsi     | 24 ++++++++++++++++++++++++
> > >  arch/arm64/boot/dts/qcom/pm8916.dtsi      |  6 ++++++
> > >  3 files changed, 54 insertions(+)
> > > 
> > > diff --git a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
> > > index 037e26b..f1c1216 100644
> > > --- a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
> > > +++ b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
> > > @@ -560,6 +560,30 @@
> > >  	qcom,mbhc-vthreshold-high = <75 150 237 450 500>;
> > >  };
> > >  
> > > +&spm_regulators {
> > > +	vdd_cpu: s2 {
> > > +		regulator-always-on;
> > > +		regulator-min-microvolt = <1050000>;
> > > +		regulator-max-microvolt = <1350000>;
> > > +	};
> > > +};
> > > +
> > > +&CPU0 {
> > > +	cpu-supply = <&vdd_cpu>;
> > > +};
> > > +
> > > +&CPU1 {
> > > +	cpu-supply = <&vdd_cpu>;
> > > +};
> > > +
> > > +&CPU2 {
> > > +	cpu-supply = <&vdd_cpu>;
> > > +};
> > > +
> > > +&CPU3 {
> > > +	cpu-supply = <&vdd_cpu>;
> > > +};
> > > +
> > 
> > I'm a bit confused about the separation here. The cpu-supply is defined
> > in the board-specific device tree, yet the voltages are set in the
> > common device tree below.
> > 
> > Is it even possible that the CPU is supplied by something other than S2
> > and if yes, how likely is this?
> > 
> > I'm asking because I have two other MSM8916 devices in mainline
> > (and a few more pending upstreaming), and it seems like I would need to
> > duplicate this into each of them.
> > 
> > Thanks,
> > Stephan
> > 
> > >  &smd_rpm_regulators {
> > >  	vdd_l1_l2_l3-supply = <&pm8916_s3>;
> > >  	vdd_l5-supply = <&pm8916_s3>;
> > > diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > > index 9f31064..9805af0 100644
> > > --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > > +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > > @@ -342,15 +342,39 @@
> > >  
> > >  		opp-200000000 {
> > >  			opp-hz = /bits/ 64 <200000000>;
> > > +			opp-microvolt = <1050000>;
> > >  		};
> > >  		opp-400000000 {
> > >  			opp-hz = /bits/ 64 <400000000>;
> > > +			opp-microvolt = <1050000>;
> > > +		};
> > > +		opp-533330000 {
> > > +			opp-hz = /bits/ 64 <533330000>;
> > > +			opp-microvolt = <1150000>;
> > >  		};
> > >  		opp-800000000 {
> > >  			opp-hz = /bits/ 64 <800000000>;
> > > +			opp-microvolt = <1150000>;
> > >  		};
> > >  		opp-998400000 {
> > >  			opp-hz = /bits/ 64 <998400000>;
> > > +			opp-microvolt = <1350000>;
> > > +		};
> > > +		opp-1094400000 {
> > > +			opp-hz = /bits/ 64 <1094400000>;
> > > +			opp-microvolt = <1350000>;
> > > +		};
> > > +		opp-1152000000 {
> > > +			opp-hz = /bits/ 64 <1152000000>;
> > > +			opp-microvolt = <1350000>;
> > > +		};
> > > +		opp-1209600000 {
> > > +			opp-hz = /bits/ 64 <1209600000>;
> > > +			opp-microvolt = <1350000>;
> > > +		};
> > > +		opp-1363200000 {
> > > +			opp-hz = /bits/ 64 <1363200000>;
> > > +			opp-microvolt = <1350000>;
> > >  		};
> > >  	};
> > >  
> > > diff --git a/arch/arm64/boot/dts/qcom/pm8916.dtsi b/arch/arm64/boot/dts/qcom/pm8916.dtsi
> > > index 0bcdf04..c9b9c4f 100644
> > > --- a/arch/arm64/boot/dts/qcom/pm8916.dtsi
> > > +++ b/arch/arm64/boot/dts/qcom/pm8916.dtsi
> > > @@ -157,5 +157,11 @@
> > >  			vdd-micbias-supply = <&pm8916_l13>;
> > >  			#sound-dai-cells = <1>;
> > >  		};
> > > +
> > > +		spm_regulators: spm_regulators  {
> > > +			compatible = "qcom,pm8916-regulators";
> > > +			#address-cells = <1>;
> > > +			#size-cells = <1>;
> > > +		};
> > >  	};
> > >  };
> > > -- 
> > > 2.7.4
> > > 

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps
  2020-04-03 10:09     ` Stephan Gerhold
@ 2020-04-03 18:00       ` Stephan Gerhold
  2020-04-23  4:55         ` Bjorn Andersson
  0 siblings, 1 reply; 32+ messages in thread
From: Stephan Gerhold @ 2020-04-03 18:00 UTC (permalink / raw)
  To: Bjorn Andersson; +Cc: Loic Poulain, agross, linux-arm-msm

On Fri, Apr 03, 2020 at 12:09:25PM +0200, Stephan Gerhold wrote:
> On Thu, Apr 02, 2020 at 06:31:19PM -0700, Bjorn Andersson wrote:
> > On Thu 02 Apr 01:13 PDT 2020, Stephan Gerhold wrote:
> > 
> > > Hi,
> > > 
> > > On Wed, Apr 01, 2020 at 07:50:59PM +0200, Loic Poulain wrote:
> > > > The highest cpu frequency opps have been dropped because CPR is not
> > > > supported. However, we can simply specify operating voltage so that
> > > > they match the max corner voltages for each freq. With that, we can
> > > > support up to 1.36Ghz. Ideally, msm8916 CPR should be implemented to
> > > > fine tune operating voltages and optimize power consumption.
> > > 
> > > Thanks for the patch! I was wondering how to enable the higher CPU
> > > frequencies for a while now...
> > > 
> > > I was actually quite excited to see CPR being mainlined for QCS404.
> > > If we are trying to add such a workaround (rather than CPR) for MSM8916
> > > now, does that mean it's unlikely to see CPR working for MSM8916
> > > anytime soon?
> > > 
> > > AFAICT, there is a WIP branch from Niklas Cassel here:
> > > https://git.linaro.org/people/nicolas.dechesne/niklas.cassel/kernel.git/log/?h=cpr-msm8916-mainline
> > > but it hasn't been updated for a while. (Not sure if it was working
> > > already...)
> > > 
> > > Can someone explain what is missing to make CPR work for MSM8916?
> > > 
> > 
> > CPR needs to control 3 things; VDD_APC, VDD_MX and MEMACC. On QCS404 it
> > seems we don't have to adjust VDD_MX, so the code for this is missing
> > from the driver.
> > 
> > So, afaict, what's missing is that rpmpd.c needs to gain support for
> > 8916, then the CPR driver needs to gain a cpr_acc_desc and compatible
> > for 8916, it needs to reference the VDDMX power domain and before/after
> > we're adjusting the corner of the CPR we need to adjust the MX according
> > to the mapping specified in the downstream kernel (i.e.  1->4, 2->5 and
> > 3->7).
> > 
> > 
> > Unfortunately, the requirement that VDDMX (VDD_MEM I presume) must be
> > higher than VDD_APC most likely needs to be taken into consideration for
> > Loic's proposed static voltage scaling as well. Unless VDD_MEM is left
> > in Turbo mode from the boot loader I think we need to take VDDMX to
> > corner 7 for speeds 998MHz and above (i.e. where we pull VDD_APC to
> > 1.35V).
> > 
> 
> I see! I wonder how hard it would be to add MSM8916 to rpmpd,
> looking at previous commits it's mainly setting up a few defines?
> 
> If I understand it correctly, the OPPs from rpmpd could then be
> referenced as "required-opps" in the CPU OPP table so that VDD_MX is
> scaled together with the CPU frequency, and doesn't need to stay at
> turbo mode (like in v3 from Loic) the whole time.
> 

I have been thinking about this some more and I think I came up with
some changes that make sense (but not entirely sure).

Based on the available downstream sources I guessed the defines to add
for MSM8916 to the rpmpd driver. Then I added the VDD_MX OPPs as
"required-opps" to the CPU OPP table so it would vote for the appopriate
corners (with the mapping you mentioned above).

I haven't tested it yet, maybe I can get some feedback first if the code
seems reasonable or if I'm missing something obvious? :)

Also: Is there a good way to validate these changes?
I suppose I could check the genpd state but that wouldn't tell me if the
corner was applied correctly. Maybe I can check the actual voltage
through the SPMI interface, hm...

If this seems like a good approach I can split up the changes in
reasonable patches and post it separately. For now the full diff below.

Stephan

 arch/arm64/boot/dts/qcom/msm8916.dtsi  | 65 +++++++++++++++++++++++++++++-----
 drivers/cpufreq/cpufreq-dt-platdev.c   |  1 +
 drivers/cpufreq/qcom-cpufreq-nvmem.c   | 11 ++++++
 drivers/soc/qcom/rpmpd.c               | 21 +++++++++++
 include/dt-bindings/power/qcom-rpmpd.h |  7 ++++
 5 files changed, 96 insertions(+), 9 deletions(-)

diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
index b0a82447976a..5b8fce8609d0 100644
--- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
@@ -10,6 +10,7 @@
 #include <dt-bindings/soc/qcom,apr.h>
 #include <dt-bindings/sound/qcom,q6afe.h>
 #include <dt-bindings/thermal/thermal.h>
+#include <dt-bindings/power/qcom-rpmpd.h>
 
 / {
 	interrupt-parent = <&intc>;
@@ -108,8 +109,8 @@ CPU0: cpu@0 {
 			cpu-supply = <&pm8916_spmi_s2>;
 			operating-points-v2 = <&cpu_opp_table>;
 			#cooling-cells = <2>;
-			power-domains = <&CPU_PD0>;
-			power-domain-names = "psci";
+			power-domains = <&CPU_PD0>, <&rpmpd MSM8916_VDDMX_AO>;
+			power-domain-names = "psci", "mx";
 		};
 
 		CPU1: cpu@1 {
@@ -122,8 +123,8 @@ CPU1: cpu@1 {
 			cpu-supply = <&pm8916_spmi_s2>;
 			operating-points-v2 = <&cpu_opp_table>;
 			#cooling-cells = <2>;
-			power-domains = <&CPU_PD1>;
-			power-domain-names = "psci";
+			power-domains = <&CPU_PD1>, <&rpmpd MSM8916_VDDMX_AO>;
+			power-domain-names = "psci", "mx";
 		};
 
 		CPU2: cpu@2 {
@@ -136,8 +137,8 @@ CPU2: cpu@2 {
 			cpu-supply = <&pm8916_spmi_s2>;
 			operating-points-v2 = <&cpu_opp_table>;
 			#cooling-cells = <2>;
-			power-domains = <&CPU_PD2>;
-			power-domain-names = "psci";
+			power-domains = <&CPU_PD2>, <&rpmpd MSM8916_VDDMX_AO>;
+			power-domain-names = "psci", "mx";
 		};
 
 		CPU3: cpu@3 {
@@ -150,8 +151,8 @@ CPU3: cpu@3 {
 			cpu-supply = <&pm8916_spmi_s2>;
 			operating-points-v2 = <&cpu_opp_table>;
 			#cooling-cells = <2>;
-			power-domains = <&CPU_PD3>;
-			power-domain-names = "psci";
+			power-domains = <&CPU_PD3>, <&rpmpd MSM8916_VDDMX_AO>;
+			power-domain-names = "psci", "mx";
 		};
 
 		L2_0: l2-cache {
@@ -343,40 +344,52 @@ modem_alert0: trip-point@0 {
 	};
 
 	cpu_opp_table: cpu_opp_table {
-		compatible = "operating-points-v2";
+		/*
+		 * FIXME: The naming here is really weird, since MSM8916 does
+		 * not have kyro. Maybe we should add a more generic compatible?
+		 */
+		compatible = "operating-points-v2-kryo-cpu";
 		opp-shared;
 
 		opp-200000000 {
 			opp-hz = /bits/ 64 <200000000>;
 			opp-microvolt = <1050000>;
+			required-opps = <&rpmpd_opp_svs_soc>;
 		};
 		opp-400000000 {
 			opp-hz = /bits/ 64 <400000000>;
 			opp-microvolt = <1050000>;
+			required-opps = <&rpmpd_opp_svs_soc>;
 		};
 		opp-533330000 {
 			opp-hz = /bits/ 64 <533330000>;
 			opp-microvolt = <1150000>;
+			required-opps = <&rpmpd_opp_nom>;
 		};
 		opp-800000000 {
 			opp-hz = /bits/ 64 <800000000>;
 			opp-microvolt = <1150000>;
+			required-opps = <&rpmpd_opp_nom>;
 		};
 		opp-998400000 {
 			opp-hz = /bits/ 64 <998400000>;
 			opp-microvolt = <1350000>;
+			required-opps = <&rpmpd_opp_super_turbo>;
 		};
 		opp-1094400000 {
 			opp-hz = /bits/ 64 <1094400000>;
 			opp-microvolt = <1350000>;
+			required-opps = <&rpmpd_opp_super_turbo>;
 		};
 		opp-1152000000 {
 			opp-hz = /bits/ 64 <1152000000>;
 			opp-microvolt = <1350000>;
+			required-opps = <&rpmpd_opp_super_turbo>;
 		};
 		opp-1209600000 {
 			opp-hz = /bits/ 64 <1209600000>;
 			opp-microvolt = <1350000>;
+			required-opps = <&rpmpd_opp_super_turbo>;
 		};
 	};
 
@@ -1710,6 +1723,40 @@ rpmcc: qcom,rpmcc {
 					#clock-cells = <1>;
 				};
 
+				rpmpd: power-controller {
+					compatible = "qcom,msm8916-rpmpd";
+					#power-domain-cells = <1>;
+					operating-points-v2 = <&rpmpd_opp_table>;
+
+					rpmpd_opp_table: opp-table {
+						compatible = "operating-points-v2";
+
+						rpmpd_opp_ret: opp1 {
+							opp-level = <1>;
+						};
+
+						rpmpd_opp_svs: opp2 {
+							opp-level = <2>;
+						};
+
+						rpmpd_opp_svs_soc: opp3 {
+							opp-level = <3>;
+						};
+
+						rpmpd_opp_nom: opp4 {
+							opp-level = <4>;
+						};
+
+						rpmpd_opp_turbo: opp5 {
+							opp-level = <5>;
+						};
+
+						rpmpd_opp_super_turbo: opp6 {
+							opp-level = <6>;
+						};
+					};
+				};
+
 				smd_rpm_regulators: pm8916-regulators {
 					compatible = "qcom,rpm-pm8916-regulators";
 
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
index f2ae9cd455c1..b0f6bd0fffc1 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -128,6 +128,7 @@ static const struct of_device_id blacklist[] __initconst = {
 	{ .compatible = "nvidia,tegra210", },
 
 	{ .compatible = "qcom,apq8096", },
+	{ .compatible = "qcom,msm8916", },
 	{ .compatible = "qcom,msm8996", },
 	{ .compatible = "qcom,qcs404", },
 
diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
index f0d2d5035413..c77a30349d08 100644
--- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
+++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
@@ -129,6 +129,16 @@ static const struct qcom_cpufreq_match_data match_data_kryo = {
 	.get_version = qcom_cpufreq_kryo_name_version,
 };
 
+static const char *msm8916_genpd_names[] = { "mx", NULL };
+
+static const struct qcom_cpufreq_match_data match_data_msm8916 = {
+	/*
+	 * FIXME: Might need to implement .get_version here to handle
+	 * different frequencies depending on speedbin/pvs version.
+	 */
+	.genpd_names = msm8916_genpd_names,
+};
+
 static const char *qcs404_genpd_names[] = { "cpr", NULL };
 
 static const struct qcom_cpufreq_match_data match_data_qcs404 = {
@@ -301,6 +311,7 @@ static struct platform_driver qcom_cpufreq_driver = {
 
 static const struct of_device_id qcom_cpufreq_match_list[] __initconst = {
 	{ .compatible = "qcom,apq8096", .data = &match_data_kryo },
+	{ .compatible = "qcom,msm8916", .data = &match_data_msm8916 },
 	{ .compatible = "qcom,msm8996", .data = &match_data_kryo },
 	{ .compatible = "qcom,qcs404", .data = &match_data_qcs404 },
 	{},
diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c
index 2b1834c5609a..192ba9099964 100644
--- a/drivers/soc/qcom/rpmpd.c
+++ b/drivers/soc/qcom/rpmpd.c
@@ -115,6 +115,26 @@ struct rpmpd_desc {
 
 static DEFINE_MUTEX(rpmpd_lock);
 
+/* msm8916 RPM Power Domains */
+DEFINE_RPMPD_PAIR(msm8916, vddcx, vddcx_ao, SMPA, CORNER, 1);
+DEFINE_RPMPD_PAIR(msm8916, vddmx, vddmx_ao, LDOA, CORNER, 3);
+
+DEFINE_RPMPD_VFC(msm8916, vddcx_vfc, SMPA, 1);
+
+static struct rpmpd *msm8916_rpmpds[] = {
+	[MSM8916_VDDCX] =	&msm8916_vddcx,
+	[MSM8916_VDDCX_AO] =	&msm8916_vddcx_ao,
+	[MSM8916_VDDCX_VFC] =	&msm8916_vddcx_vfc,
+	[MSM8916_VDDMX] =	&msm8916_vddmx,
+	[MSM8916_VDDMX_AO] =	&msm8916_vddmx_ao,
+};
+
+static const struct rpmpd_desc msm8916_desc = {
+	.rpmpds = msm8916_rpmpds,
+	.num_pds = ARRAY_SIZE(msm8916_rpmpds),
+	.max_state = MAX_8996_RPMPD_STATE,
+};
+
 /* msm8976 RPM Power Domains */
 DEFINE_RPMPD_PAIR(msm8976, vddcx, vddcx_ao, SMPA, LEVEL, 2);
 DEFINE_RPMPD_PAIR(msm8976, vddmx, vddmx_ao, SMPA, LEVEL, 6);
@@ -220,6 +240,7 @@ static const struct rpmpd_desc qcs404_desc = {
 };
 
 static const struct of_device_id rpmpd_match_table[] = {
+	{ .compatible = "qcom,msm8916-rpmpd", .data = &msm8916_desc },
 	{ .compatible = "qcom,msm8976-rpmpd", .data = &msm8976_desc },
 	{ .compatible = "qcom,msm8996-rpmpd", .data = &msm8996_desc },
 	{ .compatible = "qcom,msm8998-rpmpd", .data = &msm8998_desc },
diff --git a/include/dt-bindings/power/qcom-rpmpd.h b/include/dt-bindings/power/qcom-rpmpd.h
index 3f74096d5a7c..70d304a2deae 100644
--- a/include/dt-bindings/power/qcom-rpmpd.h
+++ b/include/dt-bindings/power/qcom-rpmpd.h
@@ -51,6 +51,13 @@
 #define RPMH_REGULATOR_LEVEL_TURBO	384
 #define RPMH_REGULATOR_LEVEL_TURBO_L1	416
 
+/* MSM8916 Power Domain Indexes */
+#define MSM8916_VDDCX		0
+#define MSM8916_VDDCX_AO	1
+#define MSM8916_VDDCX_VFC	2
+#define MSM8916_VDDMX		3
+#define MSM8916_VDDMX_AO	4
+
 /* MSM8976 Power Domain Indexes */
 #define MSM8976_VDDCX		0
 #define MSM8976_VDDCX_AO	1

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps
  2020-04-03 18:00       ` Stephan Gerhold
@ 2020-04-23  4:55         ` Bjorn Andersson
  2020-04-26 12:31           ` Stephan Gerhold
  2020-05-25 15:32           ` Niklas Cassel
  0 siblings, 2 replies; 32+ messages in thread
From: Bjorn Andersson @ 2020-04-23  4:55 UTC (permalink / raw)
  To: Stephan Gerhold; +Cc: Loic Poulain, agross, linux-arm-msm

On Fri 03 Apr 11:00 PDT 2020, Stephan Gerhold wrote:

> On Fri, Apr 03, 2020 at 12:09:25PM +0200, Stephan Gerhold wrote:
> > On Thu, Apr 02, 2020 at 06:31:19PM -0700, Bjorn Andersson wrote:
> > > On Thu 02 Apr 01:13 PDT 2020, Stephan Gerhold wrote:
> > > 
> > > > Hi,
> > > > 
> > > > On Wed, Apr 01, 2020 at 07:50:59PM +0200, Loic Poulain wrote:
> > > > > The highest cpu frequency opps have been dropped because CPR is not
> > > > > supported. However, we can simply specify operating voltage so that
> > > > > they match the max corner voltages for each freq. With that, we can
> > > > > support up to 1.36Ghz. Ideally, msm8916 CPR should be implemented to
> > > > > fine tune operating voltages and optimize power consumption.
> > > > 
> > > > Thanks for the patch! I was wondering how to enable the higher CPU
> > > > frequencies for a while now...
> > > > 
> > > > I was actually quite excited to see CPR being mainlined for QCS404.
> > > > If we are trying to add such a workaround (rather than CPR) for MSM8916
> > > > now, does that mean it's unlikely to see CPR working for MSM8916
> > > > anytime soon?
> > > > 
> > > > AFAICT, there is a WIP branch from Niklas Cassel here:
> > > > https://git.linaro.org/people/nicolas.dechesne/niklas.cassel/kernel.git/log/?h=cpr-msm8916-mainline
> > > > but it hasn't been updated for a while. (Not sure if it was working
> > > > already...)
> > > > 
> > > > Can someone explain what is missing to make CPR work for MSM8916?
> > > > 
> > > 
> > > CPR needs to control 3 things; VDD_APC, VDD_MX and MEMACC. On QCS404 it
> > > seems we don't have to adjust VDD_MX, so the code for this is missing
> > > from the driver.
> > > 
> > > So, afaict, what's missing is that rpmpd.c needs to gain support for
> > > 8916, then the CPR driver needs to gain a cpr_acc_desc and compatible
> > > for 8916, it needs to reference the VDDMX power domain and before/after
> > > we're adjusting the corner of the CPR we need to adjust the MX according
> > > to the mapping specified in the downstream kernel (i.e.  1->4, 2->5 and
> > > 3->7).
> > > 
> > > 
> > > Unfortunately, the requirement that VDDMX (VDD_MEM I presume) must be
> > > higher than VDD_APC most likely needs to be taken into consideration for
> > > Loic's proposed static voltage scaling as well. Unless VDD_MEM is left
> > > in Turbo mode from the boot loader I think we need to take VDDMX to
> > > corner 7 for speeds 998MHz and above (i.e. where we pull VDD_APC to
> > > 1.35V).
> > > 
> > 
> > I see! I wonder how hard it would be to add MSM8916 to rpmpd,
> > looking at previous commits it's mainly setting up a few defines?
> > 
> > If I understand it correctly, the OPPs from rpmpd could then be
> > referenced as "required-opps" in the CPU OPP table so that VDD_MX is
> > scaled together with the CPU frequency, and doesn't need to stay at
> > turbo mode (like in v3 from Loic) the whole time.
> > 
> 
> I have been thinking about this some more and I think I came up with
> some changes that make sense (but not entirely sure).
> 
> Based on the available downstream sources I guessed the defines to add
> for MSM8916 to the rpmpd driver. Then I added the VDD_MX OPPs as
> "required-opps" to the CPU OPP table so it would vote for the appopriate
> corners (with the mapping you mentioned above).
> 

I was not aware it was possible to describe the dependency between the
CPU opp table and MX in this fashion. If that's the case then this looks
really good and it should be straight forward to add MSM8916 support to
the CPR driver as well.

> I haven't tested it yet, maybe I can get some feedback first if the code
> seems reasonable or if I'm missing something obvious? :)
> 

Have you tested this yet?

> Also: Is there a good way to validate these changes?
> I suppose I could check the genpd state but that wouldn't tell me if the
> corner was applied correctly. Maybe I can check the actual voltage
> through the SPMI interface, hm...
> 

Validating that S2 and VDD_MX changes appropriately in Linux would be a
pretty good test.

> If this seems like a good approach I can split up the changes in
> reasonable patches and post it separately. For now the full diff below.
> 

Please do

Regards,
Bjorn

> Stephan
> 
>  arch/arm64/boot/dts/qcom/msm8916.dtsi  | 65 +++++++++++++++++++++++++++++-----
>  drivers/cpufreq/cpufreq-dt-platdev.c   |  1 +
>  drivers/cpufreq/qcom-cpufreq-nvmem.c   | 11 ++++++
>  drivers/soc/qcom/rpmpd.c               | 21 +++++++++++
>  include/dt-bindings/power/qcom-rpmpd.h |  7 ++++
>  5 files changed, 96 insertions(+), 9 deletions(-)
> 
> diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> index b0a82447976a..5b8fce8609d0 100644
> --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
> +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> @@ -10,6 +10,7 @@
>  #include <dt-bindings/soc/qcom,apr.h>
>  #include <dt-bindings/sound/qcom,q6afe.h>
>  #include <dt-bindings/thermal/thermal.h>
> +#include <dt-bindings/power/qcom-rpmpd.h>
>  
>  / {
>  	interrupt-parent = <&intc>;
> @@ -108,8 +109,8 @@ CPU0: cpu@0 {
>  			cpu-supply = <&pm8916_spmi_s2>;
>  			operating-points-v2 = <&cpu_opp_table>;
>  			#cooling-cells = <2>;
> -			power-domains = <&CPU_PD0>;
> -			power-domain-names = "psci";
> +			power-domains = <&CPU_PD0>, <&rpmpd MSM8916_VDDMX_AO>;
> +			power-domain-names = "psci", "mx";
>  		};
>  
>  		CPU1: cpu@1 {
> @@ -122,8 +123,8 @@ CPU1: cpu@1 {
>  			cpu-supply = <&pm8916_spmi_s2>;
>  			operating-points-v2 = <&cpu_opp_table>;
>  			#cooling-cells = <2>;
> -			power-domains = <&CPU_PD1>;
> -			power-domain-names = "psci";
> +			power-domains = <&CPU_PD1>, <&rpmpd MSM8916_VDDMX_AO>;
> +			power-domain-names = "psci", "mx";
>  		};
>  
>  		CPU2: cpu@2 {
> @@ -136,8 +137,8 @@ CPU2: cpu@2 {
>  			cpu-supply = <&pm8916_spmi_s2>;
>  			operating-points-v2 = <&cpu_opp_table>;
>  			#cooling-cells = <2>;
> -			power-domains = <&CPU_PD2>;
> -			power-domain-names = "psci";
> +			power-domains = <&CPU_PD2>, <&rpmpd MSM8916_VDDMX_AO>;
> +			power-domain-names = "psci", "mx";
>  		};
>  
>  		CPU3: cpu@3 {
> @@ -150,8 +151,8 @@ CPU3: cpu@3 {
>  			cpu-supply = <&pm8916_spmi_s2>;
>  			operating-points-v2 = <&cpu_opp_table>;
>  			#cooling-cells = <2>;
> -			power-domains = <&CPU_PD3>;
> -			power-domain-names = "psci";
> +			power-domains = <&CPU_PD3>, <&rpmpd MSM8916_VDDMX_AO>;
> +			power-domain-names = "psci", "mx";
>  		};
>  
>  		L2_0: l2-cache {
> @@ -343,40 +344,52 @@ modem_alert0: trip-point@0 {
>  	};
>  
>  	cpu_opp_table: cpu_opp_table {
> -		compatible = "operating-points-v2";
> +		/*
> +		 * FIXME: The naming here is really weird, since MSM8916 does
> +		 * not have kyro. Maybe we should add a more generic compatible?
> +		 */
> +		compatible = "operating-points-v2-kryo-cpu";
>  		opp-shared;
>  
>  		opp-200000000 {
>  			opp-hz = /bits/ 64 <200000000>;
>  			opp-microvolt = <1050000>;
> +			required-opps = <&rpmpd_opp_svs_soc>;
>  		};
>  		opp-400000000 {
>  			opp-hz = /bits/ 64 <400000000>;
>  			opp-microvolt = <1050000>;
> +			required-opps = <&rpmpd_opp_svs_soc>;
>  		};
>  		opp-533330000 {
>  			opp-hz = /bits/ 64 <533330000>;
>  			opp-microvolt = <1150000>;
> +			required-opps = <&rpmpd_opp_nom>;
>  		};
>  		opp-800000000 {
>  			opp-hz = /bits/ 64 <800000000>;
>  			opp-microvolt = <1150000>;
> +			required-opps = <&rpmpd_opp_nom>;
>  		};
>  		opp-998400000 {
>  			opp-hz = /bits/ 64 <998400000>;
>  			opp-microvolt = <1350000>;
> +			required-opps = <&rpmpd_opp_super_turbo>;
>  		};
>  		opp-1094400000 {
>  			opp-hz = /bits/ 64 <1094400000>;
>  			opp-microvolt = <1350000>;
> +			required-opps = <&rpmpd_opp_super_turbo>;
>  		};
>  		opp-1152000000 {
>  			opp-hz = /bits/ 64 <1152000000>;
>  			opp-microvolt = <1350000>;
> +			required-opps = <&rpmpd_opp_super_turbo>;
>  		};
>  		opp-1209600000 {
>  			opp-hz = /bits/ 64 <1209600000>;
>  			opp-microvolt = <1350000>;
> +			required-opps = <&rpmpd_opp_super_turbo>;
>  		};
>  	};
>  
> @@ -1710,6 +1723,40 @@ rpmcc: qcom,rpmcc {
>  					#clock-cells = <1>;
>  				};
>  
> +				rpmpd: power-controller {
> +					compatible = "qcom,msm8916-rpmpd";
> +					#power-domain-cells = <1>;
> +					operating-points-v2 = <&rpmpd_opp_table>;
> +
> +					rpmpd_opp_table: opp-table {
> +						compatible = "operating-points-v2";
> +
> +						rpmpd_opp_ret: opp1 {
> +							opp-level = <1>;
> +						};
> +
> +						rpmpd_opp_svs: opp2 {
> +							opp-level = <2>;
> +						};
> +
> +						rpmpd_opp_svs_soc: opp3 {
> +							opp-level = <3>;
> +						};
> +
> +						rpmpd_opp_nom: opp4 {
> +							opp-level = <4>;
> +						};
> +
> +						rpmpd_opp_turbo: opp5 {
> +							opp-level = <5>;
> +						};
> +
> +						rpmpd_opp_super_turbo: opp6 {
> +							opp-level = <6>;
> +						};
> +					};
> +				};
> +
>  				smd_rpm_regulators: pm8916-regulators {
>  					compatible = "qcom,rpm-pm8916-regulators";
>  
> diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
> index f2ae9cd455c1..b0f6bd0fffc1 100644
> --- a/drivers/cpufreq/cpufreq-dt-platdev.c
> +++ b/drivers/cpufreq/cpufreq-dt-platdev.c
> @@ -128,6 +128,7 @@ static const struct of_device_id blacklist[] __initconst = {
>  	{ .compatible = "nvidia,tegra210", },
>  
>  	{ .compatible = "qcom,apq8096", },
> +	{ .compatible = "qcom,msm8916", },
>  	{ .compatible = "qcom,msm8996", },
>  	{ .compatible = "qcom,qcs404", },
>  
> diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> index f0d2d5035413..c77a30349d08 100644
> --- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
> +++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> @@ -129,6 +129,16 @@ static const struct qcom_cpufreq_match_data match_data_kryo = {
>  	.get_version = qcom_cpufreq_kryo_name_version,
>  };
>  
> +static const char *msm8916_genpd_names[] = { "mx", NULL };
> +
> +static const struct qcom_cpufreq_match_data match_data_msm8916 = {
> +	/*
> +	 * FIXME: Might need to implement .get_version here to handle
> +	 * different frequencies depending on speedbin/pvs version.
> +	 */
> +	.genpd_names = msm8916_genpd_names,
> +};
> +
>  static const char *qcs404_genpd_names[] = { "cpr", NULL };
>  
>  static const struct qcom_cpufreq_match_data match_data_qcs404 = {
> @@ -301,6 +311,7 @@ static struct platform_driver qcom_cpufreq_driver = {
>  
>  static const struct of_device_id qcom_cpufreq_match_list[] __initconst = {
>  	{ .compatible = "qcom,apq8096", .data = &match_data_kryo },
> +	{ .compatible = "qcom,msm8916", .data = &match_data_msm8916 },
>  	{ .compatible = "qcom,msm8996", .data = &match_data_kryo },
>  	{ .compatible = "qcom,qcs404", .data = &match_data_qcs404 },
>  	{},
> diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c
> index 2b1834c5609a..192ba9099964 100644
> --- a/drivers/soc/qcom/rpmpd.c
> +++ b/drivers/soc/qcom/rpmpd.c
> @@ -115,6 +115,26 @@ struct rpmpd_desc {
>  
>  static DEFINE_MUTEX(rpmpd_lock);
>  
> +/* msm8916 RPM Power Domains */
> +DEFINE_RPMPD_PAIR(msm8916, vddcx, vddcx_ao, SMPA, CORNER, 1);
> +DEFINE_RPMPD_PAIR(msm8916, vddmx, vddmx_ao, LDOA, CORNER, 3);
> +
> +DEFINE_RPMPD_VFC(msm8916, vddcx_vfc, SMPA, 1);
> +
> +static struct rpmpd *msm8916_rpmpds[] = {
> +	[MSM8916_VDDCX] =	&msm8916_vddcx,
> +	[MSM8916_VDDCX_AO] =	&msm8916_vddcx_ao,
> +	[MSM8916_VDDCX_VFC] =	&msm8916_vddcx_vfc,
> +	[MSM8916_VDDMX] =	&msm8916_vddmx,
> +	[MSM8916_VDDMX_AO] =	&msm8916_vddmx_ao,
> +};
> +
> +static const struct rpmpd_desc msm8916_desc = {
> +	.rpmpds = msm8916_rpmpds,
> +	.num_pds = ARRAY_SIZE(msm8916_rpmpds),
> +	.max_state = MAX_8996_RPMPD_STATE,
> +};
> +
>  /* msm8976 RPM Power Domains */
>  DEFINE_RPMPD_PAIR(msm8976, vddcx, vddcx_ao, SMPA, LEVEL, 2);
>  DEFINE_RPMPD_PAIR(msm8976, vddmx, vddmx_ao, SMPA, LEVEL, 6);
> @@ -220,6 +240,7 @@ static const struct rpmpd_desc qcs404_desc = {
>  };
>  
>  static const struct of_device_id rpmpd_match_table[] = {
> +	{ .compatible = "qcom,msm8916-rpmpd", .data = &msm8916_desc },
>  	{ .compatible = "qcom,msm8976-rpmpd", .data = &msm8976_desc },
>  	{ .compatible = "qcom,msm8996-rpmpd", .data = &msm8996_desc },
>  	{ .compatible = "qcom,msm8998-rpmpd", .data = &msm8998_desc },
> diff --git a/include/dt-bindings/power/qcom-rpmpd.h b/include/dt-bindings/power/qcom-rpmpd.h
> index 3f74096d5a7c..70d304a2deae 100644
> --- a/include/dt-bindings/power/qcom-rpmpd.h
> +++ b/include/dt-bindings/power/qcom-rpmpd.h
> @@ -51,6 +51,13 @@
>  #define RPMH_REGULATOR_LEVEL_TURBO	384
>  #define RPMH_REGULATOR_LEVEL_TURBO_L1	416
>  
> +/* MSM8916 Power Domain Indexes */
> +#define MSM8916_VDDCX		0
> +#define MSM8916_VDDCX_AO	1
> +#define MSM8916_VDDCX_VFC	2
> +#define MSM8916_VDDMX		3
> +#define MSM8916_VDDMX_AO	4
> +
>  /* MSM8976 Power Domain Indexes */
>  #define MSM8976_VDDCX		0
>  #define MSM8976_VDDCX_AO	1

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps
  2020-04-23  4:55         ` Bjorn Andersson
@ 2020-04-26 12:31           ` Stephan Gerhold
  2020-05-06 21:18             ` Stephan Gerhold
  2020-05-25 15:32           ` Niklas Cassel
  1 sibling, 1 reply; 32+ messages in thread
From: Stephan Gerhold @ 2020-04-26 12:31 UTC (permalink / raw)
  To: Bjorn Andersson; +Cc: Loic Poulain, agross, linux-arm-msm

On Wed, Apr 22, 2020 at 09:55:06PM -0700, Bjorn Andersson wrote:
> On Fri 03 Apr 11:00 PDT 2020, Stephan Gerhold wrote:
> 
> > On Fri, Apr 03, 2020 at 12:09:25PM +0200, Stephan Gerhold wrote:
> > > On Thu, Apr 02, 2020 at 06:31:19PM -0700, Bjorn Andersson wrote:
> > > > On Thu 02 Apr 01:13 PDT 2020, Stephan Gerhold wrote:
> > > > 
> > > > > Hi,
> > > > > 
> > > > > On Wed, Apr 01, 2020 at 07:50:59PM +0200, Loic Poulain wrote:
> > > > > > The highest cpu frequency opps have been dropped because CPR is not
> > > > > > supported. However, we can simply specify operating voltage so that
> > > > > > they match the max corner voltages for each freq. With that, we can
> > > > > > support up to 1.36Ghz. Ideally, msm8916 CPR should be implemented to
> > > > > > fine tune operating voltages and optimize power consumption.
> > > > > 
> > > > > Thanks for the patch! I was wondering how to enable the higher CPU
> > > > > frequencies for a while now...
> > > > > 
> > > > > I was actually quite excited to see CPR being mainlined for QCS404.
> > > > > If we are trying to add such a workaround (rather than CPR) for MSM8916
> > > > > now, does that mean it's unlikely to see CPR working for MSM8916
> > > > > anytime soon?
> > > > > 
> > > > > AFAICT, there is a WIP branch from Niklas Cassel here:
> > > > > https://git.linaro.org/people/nicolas.dechesne/niklas.cassel/kernel.git/log/?h=cpr-msm8916-mainline
> > > > > but it hasn't been updated for a while. (Not sure if it was working
> > > > > already...)
> > > > > 
> > > > > Can someone explain what is missing to make CPR work for MSM8916?
> > > > > 
> > > > 
> > > > CPR needs to control 3 things; VDD_APC, VDD_MX and MEMACC. On QCS404 it
> > > > seems we don't have to adjust VDD_MX, so the code for this is missing
> > > > from the driver.
> > > > 
> > > > So, afaict, what's missing is that rpmpd.c needs to gain support for
> > > > 8916, then the CPR driver needs to gain a cpr_acc_desc and compatible
> > > > for 8916, it needs to reference the VDDMX power domain and before/after
> > > > we're adjusting the corner of the CPR we need to adjust the MX according
> > > > to the mapping specified in the downstream kernel (i.e.  1->4, 2->5 and
> > > > 3->7).
> > > > 
> > > > 
> > > > Unfortunately, the requirement that VDDMX (VDD_MEM I presume) must be
> > > > higher than VDD_APC most likely needs to be taken into consideration for
> > > > Loic's proposed static voltage scaling as well. Unless VDD_MEM is left
> > > > in Turbo mode from the boot loader I think we need to take VDDMX to
> > > > corner 7 for speeds 998MHz and above (i.e. where we pull VDD_APC to
> > > > 1.35V).
> > > > 
> > > 
> > > I see! I wonder how hard it would be to add MSM8916 to rpmpd,
> > > looking at previous commits it's mainly setting up a few defines?
> > > 
> > > If I understand it correctly, the OPPs from rpmpd could then be
> > > referenced as "required-opps" in the CPU OPP table so that VDD_MX is
> > > scaled together with the CPU frequency, and doesn't need to stay at
> > > turbo mode (like in v3 from Loic) the whole time.
> > > 
> > 
> > I have been thinking about this some more and I think I came up with
> > some changes that make sense (but not entirely sure).
> > 
> > Based on the available downstream sources I guessed the defines to add
> > for MSM8916 to the rpmpd driver. Then I added the VDD_MX OPPs as
> > "required-opps" to the CPU OPP table so it would vote for the appopriate
> > corners (with the mapping you mentioned above).
> > 
> 
> I was not aware it was possible to describe the dependency between the
> CPU opp table and MX in this fashion. If that's the case then this looks
> really good and it should be straight forward to add MSM8916 support to
> the CPR driver as well.
> 

Indeed!

> > I haven't tested it yet, maybe I can get some feedback first if the code
> > seems reasonable or if I'm missing something obvious? :)
> > 
> 
> Have you tested this yet?
> 

I just did. It does not fully work, yet:

rpmpd_set_performance() is indeed called as necessary when switching the
CPU frequency. When I set 200 MHz it sets corner 3, with 533 MHz corner 4
and starting with 998 MHz corner 6. So far so good :)

However, there is never actually anything sent to the RPM. :(
It bails out in rpmpd_set_performance() before calling rpmpd_aggregate_corner():

	/* Always send updates for vfc and vfl */
	if (!pd->enabled && pd->key != KEY_FLOOR_CORNER &&
	    pd->key != KEY_FLOOR_LEVEL)
		goto out;

Seems like we just try to set performance states, but never actually
enable (rpmpd_power_on()) the power domain (pd->enabled == false).

I'm not sure which of the components involved here should handle that.
The OPP core when setting required OPPs, the genpd core etc.

Any ideas?

Thanks,
Stephan

> > Also: Is there a good way to validate these changes?
> > I suppose I could check the genpd state but that wouldn't tell me if the
> > corner was applied correctly. Maybe I can check the actual voltage
> > through the SPMI interface, hm...
> > 
> 
> Validating that S2 and VDD_MX changes appropriately in Linux would be a
> pretty good test.
> 
> > If this seems like a good approach I can split up the changes in
> > reasonable patches and post it separately. For now the full diff below.
> > 
> 
> Please do
> 
> Regards,
> Bjorn
> 
> > Stephan
> > 
> >  arch/arm64/boot/dts/qcom/msm8916.dtsi  | 65 +++++++++++++++++++++++++++++-----
> >  drivers/cpufreq/cpufreq-dt-platdev.c   |  1 +
> >  drivers/cpufreq/qcom-cpufreq-nvmem.c   | 11 ++++++
> >  drivers/soc/qcom/rpmpd.c               | 21 +++++++++++
> >  include/dt-bindings/power/qcom-rpmpd.h |  7 ++++
> >  5 files changed, 96 insertions(+), 9 deletions(-)
> > 
> > diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > index b0a82447976a..5b8fce8609d0 100644
> > --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > @@ -10,6 +10,7 @@
> >  #include <dt-bindings/soc/qcom,apr.h>
> >  #include <dt-bindings/sound/qcom,q6afe.h>
> >  #include <dt-bindings/thermal/thermal.h>
> > +#include <dt-bindings/power/qcom-rpmpd.h>
> >  
> >  / {
> >  	interrupt-parent = <&intc>;
> > @@ -108,8 +109,8 @@ CPU0: cpu@0 {
> >  			cpu-supply = <&pm8916_spmi_s2>;
> >  			operating-points-v2 = <&cpu_opp_table>;
> >  			#cooling-cells = <2>;
> > -			power-domains = <&CPU_PD0>;
> > -			power-domain-names = "psci";
> > +			power-domains = <&CPU_PD0>, <&rpmpd MSM8916_VDDMX_AO>;
> > +			power-domain-names = "psci", "mx";
> >  		};
> >  
> >  		CPU1: cpu@1 {
> > @@ -122,8 +123,8 @@ CPU1: cpu@1 {
> >  			cpu-supply = <&pm8916_spmi_s2>;
> >  			operating-points-v2 = <&cpu_opp_table>;
> >  			#cooling-cells = <2>;
> > -			power-domains = <&CPU_PD1>;
> > -			power-domain-names = "psci";
> > +			power-domains = <&CPU_PD1>, <&rpmpd MSM8916_VDDMX_AO>;
> > +			power-domain-names = "psci", "mx";
> >  		};
> >  
> >  		CPU2: cpu@2 {
> > @@ -136,8 +137,8 @@ CPU2: cpu@2 {
> >  			cpu-supply = <&pm8916_spmi_s2>;
> >  			operating-points-v2 = <&cpu_opp_table>;
> >  			#cooling-cells = <2>;
> > -			power-domains = <&CPU_PD2>;
> > -			power-domain-names = "psci";
> > +			power-domains = <&CPU_PD2>, <&rpmpd MSM8916_VDDMX_AO>;
> > +			power-domain-names = "psci", "mx";
> >  		};
> >  
> >  		CPU3: cpu@3 {
> > @@ -150,8 +151,8 @@ CPU3: cpu@3 {
> >  			cpu-supply = <&pm8916_spmi_s2>;
> >  			operating-points-v2 = <&cpu_opp_table>;
> >  			#cooling-cells = <2>;
> > -			power-domains = <&CPU_PD3>;
> > -			power-domain-names = "psci";
> > +			power-domains = <&CPU_PD3>, <&rpmpd MSM8916_VDDMX_AO>;
> > +			power-domain-names = "psci", "mx";
> >  		};
> >  
> >  		L2_0: l2-cache {
> > @@ -343,40 +344,52 @@ modem_alert0: trip-point@0 {
> >  	};
> >  
> >  	cpu_opp_table: cpu_opp_table {
> > -		compatible = "operating-points-v2";
> > +		/*
> > +		 * FIXME: The naming here is really weird, since MSM8916 does
> > +		 * not have kyro. Maybe we should add a more generic compatible?
> > +		 */
> > +		compatible = "operating-points-v2-kryo-cpu";
> >  		opp-shared;
> >  
> >  		opp-200000000 {
> >  			opp-hz = /bits/ 64 <200000000>;
> >  			opp-microvolt = <1050000>;
> > +			required-opps = <&rpmpd_opp_svs_soc>;
> >  		};
> >  		opp-400000000 {
> >  			opp-hz = /bits/ 64 <400000000>;
> >  			opp-microvolt = <1050000>;
> > +			required-opps = <&rpmpd_opp_svs_soc>;
> >  		};
> >  		opp-533330000 {
> >  			opp-hz = /bits/ 64 <533330000>;
> >  			opp-microvolt = <1150000>;
> > +			required-opps = <&rpmpd_opp_nom>;
> >  		};
> >  		opp-800000000 {
> >  			opp-hz = /bits/ 64 <800000000>;
> >  			opp-microvolt = <1150000>;
> > +			required-opps = <&rpmpd_opp_nom>;
> >  		};
> >  		opp-998400000 {
> >  			opp-hz = /bits/ 64 <998400000>;
> >  			opp-microvolt = <1350000>;
> > +			required-opps = <&rpmpd_opp_super_turbo>;
> >  		};
> >  		opp-1094400000 {
> >  			opp-hz = /bits/ 64 <1094400000>;
> >  			opp-microvolt = <1350000>;
> > +			required-opps = <&rpmpd_opp_super_turbo>;
> >  		};
> >  		opp-1152000000 {
> >  			opp-hz = /bits/ 64 <1152000000>;
> >  			opp-microvolt = <1350000>;
> > +			required-opps = <&rpmpd_opp_super_turbo>;
> >  		};
> >  		opp-1209600000 {
> >  			opp-hz = /bits/ 64 <1209600000>;
> >  			opp-microvolt = <1350000>;
> > +			required-opps = <&rpmpd_opp_super_turbo>;
> >  		};
> >  	};
> >  
> > @@ -1710,6 +1723,40 @@ rpmcc: qcom,rpmcc {
> >  					#clock-cells = <1>;
> >  				};
> >  
> > +				rpmpd: power-controller {
> > +					compatible = "qcom,msm8916-rpmpd";
> > +					#power-domain-cells = <1>;
> > +					operating-points-v2 = <&rpmpd_opp_table>;
> > +
> > +					rpmpd_opp_table: opp-table {
> > +						compatible = "operating-points-v2";
> > +
> > +						rpmpd_opp_ret: opp1 {
> > +							opp-level = <1>;
> > +						};
> > +
> > +						rpmpd_opp_svs: opp2 {
> > +							opp-level = <2>;
> > +						};
> > +
> > +						rpmpd_opp_svs_soc: opp3 {
> > +							opp-level = <3>;
> > +						};
> > +
> > +						rpmpd_opp_nom: opp4 {
> > +							opp-level = <4>;
> > +						};
> > +
> > +						rpmpd_opp_turbo: opp5 {
> > +							opp-level = <5>;
> > +						};
> > +
> > +						rpmpd_opp_super_turbo: opp6 {
> > +							opp-level = <6>;
> > +						};
> > +					};
> > +				};
> > +
> >  				smd_rpm_regulators: pm8916-regulators {
> >  					compatible = "qcom,rpm-pm8916-regulators";
> >  
> > diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
> > index f2ae9cd455c1..b0f6bd0fffc1 100644
> > --- a/drivers/cpufreq/cpufreq-dt-platdev.c
> > +++ b/drivers/cpufreq/cpufreq-dt-platdev.c
> > @@ -128,6 +128,7 @@ static const struct of_device_id blacklist[] __initconst = {
> >  	{ .compatible = "nvidia,tegra210", },
> >  
> >  	{ .compatible = "qcom,apq8096", },
> > +	{ .compatible = "qcom,msm8916", },
> >  	{ .compatible = "qcom,msm8996", },
> >  	{ .compatible = "qcom,qcs404", },
> >  
> > diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > index f0d2d5035413..c77a30349d08 100644
> > --- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > +++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > @@ -129,6 +129,16 @@ static const struct qcom_cpufreq_match_data match_data_kryo = {
> >  	.get_version = qcom_cpufreq_kryo_name_version,
> >  };
> >  
> > +static const char *msm8916_genpd_names[] = { "mx", NULL };
> > +
> > +static const struct qcom_cpufreq_match_data match_data_msm8916 = {
> > +	/*
> > +	 * FIXME: Might need to implement .get_version here to handle
> > +	 * different frequencies depending on speedbin/pvs version.
> > +	 */
> > +	.genpd_names = msm8916_genpd_names,
> > +};
> > +
> >  static const char *qcs404_genpd_names[] = { "cpr", NULL };
> >  
> >  static const struct qcom_cpufreq_match_data match_data_qcs404 = {
> > @@ -301,6 +311,7 @@ static struct platform_driver qcom_cpufreq_driver = {
> >  
> >  static const struct of_device_id qcom_cpufreq_match_list[] __initconst = {
> >  	{ .compatible = "qcom,apq8096", .data = &match_data_kryo },
> > +	{ .compatible = "qcom,msm8916", .data = &match_data_msm8916 },
> >  	{ .compatible = "qcom,msm8996", .data = &match_data_kryo },
> >  	{ .compatible = "qcom,qcs404", .data = &match_data_qcs404 },
> >  	{},
> > diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c
> > index 2b1834c5609a..192ba9099964 100644
> > --- a/drivers/soc/qcom/rpmpd.c
> > +++ b/drivers/soc/qcom/rpmpd.c
> > @@ -115,6 +115,26 @@ struct rpmpd_desc {
> >  
> >  static DEFINE_MUTEX(rpmpd_lock);
> >  
> > +/* msm8916 RPM Power Domains */
> > +DEFINE_RPMPD_PAIR(msm8916, vddcx, vddcx_ao, SMPA, CORNER, 1);
> > +DEFINE_RPMPD_PAIR(msm8916, vddmx, vddmx_ao, LDOA, CORNER, 3);
> > +
> > +DEFINE_RPMPD_VFC(msm8916, vddcx_vfc, SMPA, 1);
> > +
> > +static struct rpmpd *msm8916_rpmpds[] = {
> > +	[MSM8916_VDDCX] =	&msm8916_vddcx,
> > +	[MSM8916_VDDCX_AO] =	&msm8916_vddcx_ao,
> > +	[MSM8916_VDDCX_VFC] =	&msm8916_vddcx_vfc,
> > +	[MSM8916_VDDMX] =	&msm8916_vddmx,
> > +	[MSM8916_VDDMX_AO] =	&msm8916_vddmx_ao,
> > +};
> > +
> > +static const struct rpmpd_desc msm8916_desc = {
> > +	.rpmpds = msm8916_rpmpds,
> > +	.num_pds = ARRAY_SIZE(msm8916_rpmpds),
> > +	.max_state = MAX_8996_RPMPD_STATE,
> > +};
> > +
> >  /* msm8976 RPM Power Domains */
> >  DEFINE_RPMPD_PAIR(msm8976, vddcx, vddcx_ao, SMPA, LEVEL, 2);
> >  DEFINE_RPMPD_PAIR(msm8976, vddmx, vddmx_ao, SMPA, LEVEL, 6);
> > @@ -220,6 +240,7 @@ static const struct rpmpd_desc qcs404_desc = {
> >  };
> >  
> >  static const struct of_device_id rpmpd_match_table[] = {
> > +	{ .compatible = "qcom,msm8916-rpmpd", .data = &msm8916_desc },
> >  	{ .compatible = "qcom,msm8976-rpmpd", .data = &msm8976_desc },
> >  	{ .compatible = "qcom,msm8996-rpmpd", .data = &msm8996_desc },
> >  	{ .compatible = "qcom,msm8998-rpmpd", .data = &msm8998_desc },
> > diff --git a/include/dt-bindings/power/qcom-rpmpd.h b/include/dt-bindings/power/qcom-rpmpd.h
> > index 3f74096d5a7c..70d304a2deae 100644
> > --- a/include/dt-bindings/power/qcom-rpmpd.h
> > +++ b/include/dt-bindings/power/qcom-rpmpd.h
> > @@ -51,6 +51,13 @@
> >  #define RPMH_REGULATOR_LEVEL_TURBO	384
> >  #define RPMH_REGULATOR_LEVEL_TURBO_L1	416
> >  
> > +/* MSM8916 Power Domain Indexes */
> > +#define MSM8916_VDDCX		0
> > +#define MSM8916_VDDCX_AO	1
> > +#define MSM8916_VDDCX_VFC	2
> > +#define MSM8916_VDDMX		3
> > +#define MSM8916_VDDMX_AO	4
> > +
> >  /* MSM8976 Power Domain Indexes */
> >  #define MSM8976_VDDCX		0
> >  #define MSM8976_VDDCX_AO	1

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps
  2020-04-01 17:50 [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps Loic Poulain
  2020-04-01 23:46 ` Bjorn Andersson
  2020-04-02  8:13 ` Stephan Gerhold
@ 2020-04-28 20:04 ` Amit Kucheria
  2 siblings, 0 replies; 32+ messages in thread
From: Amit Kucheria @ 2020-04-28 20:04 UTC (permalink / raw)
  To: Loic Poulain; +Cc: Bjorn Andersson, Andy Gross, linux-arm-msm

Hi Loic,

On Wed, Apr 1, 2020 at 11:17 PM Loic Poulain <loic.poulain@linaro.org> wrote:
>
> The highest cpu frequency opps have been dropped because CPR is not
> supported. However, we can simply specify operating voltage so that
> they match the max corner voltages for each freq. With that, we can
> support up to 1.36Ghz. Ideally, msm8916 CPR should be implemented to
> fine tune operating voltages and optimize power consumption.
>
> This patch:
> - Adds missing opps and corresponding target voltages to msm8916.dtsi.
> - Adds cpu-supply to apq8016-sbc.dtsi (board level info).
> - Adds pm8916 spmi regulator node to pm8916.dtsi.
>
> Tested with a dragonboard-410c.

FWIW, I took this out for a spin with stress-ng loads. The first
output is w/o the patch.

--o amitrootfs o--(/sys/devices/system/cpu/cpufreq/policy0/stats) $ grep "" *
grep: reset: Permission denied
time_in_state:200000 14304
time_in_state:400000 2
time_in_state:800000 40
time_in_state:998400 4316
total_trans:31
trans_table:   From  :    To
trans_table:         :    200000    400000    800000    998400
trans_table:   200000:         0         1        12         1
trans_table:   400000:         2         0         0         0
trans_table:   800000:        12         0         0         1
trans_table:   998400:         0         1         1         0

The following output is with the patch applied. The cpu ran at 1.3GHz
for a short while until thermal kicked in and throttled the device to
800MHz-1GHz OPPs.

--o amitrootfs o--(/sys/devices/system/cpu/cpufreq/policy0/stats) $ grep "" *
grep: reset: Permission denied
time_in_state:200000 201824
time_in_state:400000 158
time_in_state:533330 2501
time_in_state:800000 37804
time_in_state:998400 23326
time_in_state:1094400 2325
time_in_state:1152000 747
time_in_state:1209600 922
time_in_state:1363200 10788
total_trans:1504
trans_table:   From  :    To
trans_table:         :    200000    400000    533330    800000
998400   1094400   1152000   1209600   1363200
trans_table:   200000:         0        18         5         8
99         0         1         0         2
trans_table:   400000:        18         0         0         0
3         0         0         0         0
trans_table:   533330:         7         1         0        77
1         0         0         0         0
trans_table:   800000:        13         1         1         0
547         0         0         0         1
trans_table:   998400:        92         1        80       477
0        12         0         0         2
trans_table:  1094400:         1         0         0         0
14         0         0         0         2
trans_table:  1152000:         1         0         0         0
1         4         0         0         1
trans_table:  1209600:         0         0         0         0
0         0         5         0         0
trans_table:  1363200:         1         0         0         0
0         1         1         5         0



> Signed-off-by: Loic Poulain <loic.poulain@linaro.org>

I haven't found a v2 of this patch incorporating Bjorn's suggestions
yet. Until then,

Tested-by: Amit Kucheria <amit.kucheria@linaro.org>



> ---
>  arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi | 24 ++++++++++++++++++++++++
>  arch/arm64/boot/dts/qcom/msm8916.dtsi     | 24 ++++++++++++++++++++++++
>  arch/arm64/boot/dts/qcom/pm8916.dtsi      |  6 ++++++
>  3 files changed, 54 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
> index 037e26b..f1c1216 100644
> --- a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
> +++ b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
> @@ -560,6 +560,30 @@
>         qcom,mbhc-vthreshold-high = <75 150 237 450 500>;
>  };
>
> +&spm_regulators {
> +       vdd_cpu: s2 {
> +               regulator-always-on;
> +               regulator-min-microvolt = <1050000>;
> +               regulator-max-microvolt = <1350000>;
> +       };
> +};
> +
> +&CPU0 {
> +       cpu-supply = <&vdd_cpu>;
> +};
> +
> +&CPU1 {
> +       cpu-supply = <&vdd_cpu>;
> +};
> +
> +&CPU2 {
> +       cpu-supply = <&vdd_cpu>;
> +};
> +
> +&CPU3 {
> +       cpu-supply = <&vdd_cpu>;
> +};
> +
>  &smd_rpm_regulators {
>         vdd_l1_l2_l3-supply = <&pm8916_s3>;
>         vdd_l5-supply = <&pm8916_s3>;
> diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> index 9f31064..9805af0 100644
> --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
> +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> @@ -342,15 +342,39 @@
>
>                 opp-200000000 {
>                         opp-hz = /bits/ 64 <200000000>;
> +                       opp-microvolt = <1050000>;
>                 };
>                 opp-400000000 {
>                         opp-hz = /bits/ 64 <400000000>;
> +                       opp-microvolt = <1050000>;
> +               };
> +               opp-533330000 {
> +                       opp-hz = /bits/ 64 <533330000>;
> +                       opp-microvolt = <1150000>;
>                 };
>                 opp-800000000 {
>                         opp-hz = /bits/ 64 <800000000>;
> +                       opp-microvolt = <1150000>;
>                 };
>                 opp-998400000 {
>                         opp-hz = /bits/ 64 <998400000>;
> +                       opp-microvolt = <1350000>;
> +               };
> +               opp-1094400000 {
> +                       opp-hz = /bits/ 64 <1094400000>;
> +                       opp-microvolt = <1350000>;
> +               };
> +               opp-1152000000 {
> +                       opp-hz = /bits/ 64 <1152000000>;
> +                       opp-microvolt = <1350000>;
> +               };
> +               opp-1209600000 {
> +                       opp-hz = /bits/ 64 <1209600000>;
> +                       opp-microvolt = <1350000>;
> +               };
> +               opp-1363200000 {
> +                       opp-hz = /bits/ 64 <1363200000>;
> +                       opp-microvolt = <1350000>;
>                 };
>         };
>
> diff --git a/arch/arm64/boot/dts/qcom/pm8916.dtsi b/arch/arm64/boot/dts/qcom/pm8916.dtsi
> index 0bcdf04..c9b9c4f 100644
> --- a/arch/arm64/boot/dts/qcom/pm8916.dtsi
> +++ b/arch/arm64/boot/dts/qcom/pm8916.dtsi
> @@ -157,5 +157,11 @@
>                         vdd-micbias-supply = <&pm8916_l13>;
>                         #sound-dai-cells = <1>;
>                 };
> +
> +               spm_regulators: spm_regulators  {
> +                       compatible = "qcom,pm8916-regulators";
> +                       #address-cells = <1>;
> +                       #size-cells = <1>;
> +               };
>         };
>  };
> --
> 2.7.4
>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps
  2020-04-26 12:31           ` Stephan Gerhold
@ 2020-05-06 21:18             ` Stephan Gerhold
  2020-05-07  5:34               ` Bjorn Andersson
  2020-05-07 10:46               ` Stephan Gerhold
  0 siblings, 2 replies; 32+ messages in thread
From: Stephan Gerhold @ 2020-05-06 21:18 UTC (permalink / raw)
  To: Bjorn Andersson; +Cc: Loic Poulain, agross, linux-arm-msm

Hi,

On Sun, Apr 26, 2020 at 02:31:48PM +0200, Stephan Gerhold wrote:
> On Wed, Apr 22, 2020 at 09:55:06PM -0700, Bjorn Andersson wrote:
> > On Fri 03 Apr 11:00 PDT 2020, Stephan Gerhold wrote:
> > 
> > > On Fri, Apr 03, 2020 at 12:09:25PM +0200, Stephan Gerhold wrote:
> > > > On Thu, Apr 02, 2020 at 06:31:19PM -0700, Bjorn Andersson wrote:
> > > > > On Thu 02 Apr 01:13 PDT 2020, Stephan Gerhold wrote:
> > > > > 
> > > > > > Hi,
> > > > > > 
> > > > > > On Wed, Apr 01, 2020 at 07:50:59PM +0200, Loic Poulain wrote:
> > > > > > > The highest cpu frequency opps have been dropped because CPR is not
> > > > > > > supported. However, we can simply specify operating voltage so that
> > > > > > > they match the max corner voltages for each freq. With that, we can
> > > > > > > support up to 1.36Ghz. Ideally, msm8916 CPR should be implemented to
> > > > > > > fine tune operating voltages and optimize power consumption.
> > > > > > 
> > > > > > Thanks for the patch! I was wondering how to enable the higher CPU
> > > > > > frequencies for a while now...
> > > > > > 
> > > > > > I was actually quite excited to see CPR being mainlined for QCS404.
> > > > > > If we are trying to add such a workaround (rather than CPR) for MSM8916
> > > > > > now, does that mean it's unlikely to see CPR working for MSM8916
> > > > > > anytime soon?
> > > > > > 
> > > > > > AFAICT, there is a WIP branch from Niklas Cassel here:
> > > > > > https://git.linaro.org/people/nicolas.dechesne/niklas.cassel/kernel.git/log/?h=cpr-msm8916-mainline
> > > > > > but it hasn't been updated for a while. (Not sure if it was working
> > > > > > already...)
> > > > > > 
> > > > > > Can someone explain what is missing to make CPR work for MSM8916?
> > > > > > 
> > > > > 
> > > > > CPR needs to control 3 things; VDD_APC, VDD_MX and MEMACC. On QCS404 it
> > > > > seems we don't have to adjust VDD_MX, so the code for this is missing
> > > > > from the driver.
> > > > > 
> > > > > So, afaict, what's missing is that rpmpd.c needs to gain support for
> > > > > 8916, then the CPR driver needs to gain a cpr_acc_desc and compatible
> > > > > for 8916, it needs to reference the VDDMX power domain and before/after
> > > > > we're adjusting the corner of the CPR we need to adjust the MX according
> > > > > to the mapping specified in the downstream kernel (i.e.  1->4, 2->5 and
> > > > > 3->7).
> > > > > 
> > > > > 
> > > > > Unfortunately, the requirement that VDDMX (VDD_MEM I presume) must be
> > > > > higher than VDD_APC most likely needs to be taken into consideration for
> > > > > Loic's proposed static voltage scaling as well. Unless VDD_MEM is left
> > > > > in Turbo mode from the boot loader I think we need to take VDDMX to
> > > > > corner 7 for speeds 998MHz and above (i.e. where we pull VDD_APC to
> > > > > 1.35V).
> > > > > 
> > > > 
> > > > I see! I wonder how hard it would be to add MSM8916 to rpmpd,
> > > > looking at previous commits it's mainly setting up a few defines?
> > > > 
> > > > If I understand it correctly, the OPPs from rpmpd could then be
> > > > referenced as "required-opps" in the CPU OPP table so that VDD_MX is
> > > > scaled together with the CPU frequency, and doesn't need to stay at
> > > > turbo mode (like in v3 from Loic) the whole time.
> > > > 
> > > 
> > > I have been thinking about this some more and I think I came up with
> > > some changes that make sense (but not entirely sure).
> > > 
> > > Based on the available downstream sources I guessed the defines to add
> > > for MSM8916 to the rpmpd driver. Then I added the VDD_MX OPPs as
> > > "required-opps" to the CPU OPP table so it would vote for the appopriate
> > > corners (with the mapping you mentioned above).
> > > 
> > 
> > I was not aware it was possible to describe the dependency between the
> > CPU opp table and MX in this fashion. If that's the case then this looks
> > really good and it should be straight forward to add MSM8916 support to
> > the CPR driver as well.
> > 
> 
> Indeed!
> 
> > > I haven't tested it yet, maybe I can get some feedback first if the code
> > > seems reasonable or if I'm missing something obvious? :)
> > > 
> > 
> > Have you tested this yet?
> > 
> 
> I just did. It does not fully work, yet:
> 
> rpmpd_set_performance() is indeed called as necessary when switching the
> CPU frequency. When I set 200 MHz it sets corner 3, with 533 MHz corner 4
> and starting with 998 MHz corner 6. So far so good :)
> 
> However, there is never actually anything sent to the RPM. :(
> It bails out in rpmpd_set_performance() before calling rpmpd_aggregate_corner():
> 
> 	/* Always send updates for vfc and vfl */
> 	if (!pd->enabled && pd->key != KEY_FLOOR_CORNER &&
> 	    pd->key != KEY_FLOOR_LEVEL)
> 		goto out;
> 
> Seems like we just try to set performance states, but never actually
> enable (rpmpd_power_on()) the power domain (pd->enabled == false).
> 
> I'm not sure which of the components involved here should handle that.
> The OPP core when setting required OPPs, the genpd core etc.
>
> Any ideas?
> 
> Thanks,
> Stephan
> 

For now I have added something to qcom-cpufreq-nvmem.c to power on/enable
the power domain (not really sure if it belongs there...):

diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
index a1b8238872a2..ed352ead037e 100644
--- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
+++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
@@ -26,6 +26,7 @@
 #include <linux/platform_device.h>
 #include <linux/pm_domain.h>
 #include <linux/pm_opp.h>
+#include <linux/pm_runtime.h>
 #include <linux/slab.h>
 #include <linux/soc/qcom/smem.h>
 
@@ -370,10 +371,13 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
 		}
 
 		if (drv->data->genpd_names) {
+			struct device **pd_dev;
+			const char **name = drv->data->genpd_names;
+
 			drv->genpd_opp_tables[cpu] =
 				dev_pm_opp_attach_genpd(cpu_dev,
 							drv->data->genpd_names,
-							NULL);
+							&pd_dev);
 			if (IS_ERR(drv->genpd_opp_tables[cpu])) {
 				ret = PTR_ERR(drv->genpd_opp_tables[cpu]);
 				if (ret != -EPROBE_DEFER)
@@ -382,6 +386,12 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
 						ret);
 				goto free_genpd_opp;
 			}
+
+			while (*name) {
+				pm_runtime_get_sync(*pd_dev);
+				name++;
+				pd_dev++;
+			}
 		}
 	}

I really wonder why this doesn't affect CPR (or does it?).
So far I was not able to find anything that would power on/enable
the "cpr" power domain either. But I don't have a qcs404 to verify.
 
As far as I can tell from the log, the corner votes are correctly sent
to the RPM now when the CPU frequency is changed.

However...

> > > Also: Is there a good way to validate these changes?
> > > I suppose I could check the genpd state but that wouldn't tell me if the
> > > corner was applied correctly. Maybe I can check the actual voltage
> > > through the SPMI interface, hm...
> > > 
> > 
> > Validating that S2 and VDD_MX changes appropriately in Linux would be a
> > pretty good test.
> > 

Unfortunately I was not able to see any change in the voltage of L3 yet.
On samsung-a5u, /sys/class/regulator/<l3 spmi regulator>/microvolts
permanently reports 1300000 uV, even after a few different corner votes.

I'm not sure if:

  - This is normal (maybe some other remoteproc has a higher vote?)
    - I tried to disable wcnss, venus and hexagon without difference

  - I'm just missing something in the code

  - This is some peculiarity of the RPM firmware on samsung-a5u.
    (Although that seems quite unlikely to me...)

Any ideas? :/

Thanks,
Stephan

> > > If this seems like a good approach I can split up the changes in
> > > reasonable patches and post it separately. For now the full diff below.
> > > 
> > 
> > Please do
> > 
> > Regards,
> > Bjorn
> > 
> > > Stephan
> > > 
> > >  arch/arm64/boot/dts/qcom/msm8916.dtsi  | 65 +++++++++++++++++++++++++++++-----
> > >  drivers/cpufreq/cpufreq-dt-platdev.c   |  1 +
> > >  drivers/cpufreq/qcom-cpufreq-nvmem.c   | 11 ++++++
> > >  drivers/soc/qcom/rpmpd.c               | 21 +++++++++++
> > >  include/dt-bindings/power/qcom-rpmpd.h |  7 ++++
> > >  5 files changed, 96 insertions(+), 9 deletions(-)
> > > 
> > > diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > > index b0a82447976a..5b8fce8609d0 100644
> > > --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > > +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > > @@ -10,6 +10,7 @@
> > >  #include <dt-bindings/soc/qcom,apr.h>
> > >  #include <dt-bindings/sound/qcom,q6afe.h>
> > >  #include <dt-bindings/thermal/thermal.h>
> > > +#include <dt-bindings/power/qcom-rpmpd.h>
> > >  
> > >  / {
> > >  	interrupt-parent = <&intc>;
> > > @@ -108,8 +109,8 @@ CPU0: cpu@0 {
> > >  			cpu-supply = <&pm8916_spmi_s2>;
> > >  			operating-points-v2 = <&cpu_opp_table>;
> > >  			#cooling-cells = <2>;
> > > -			power-domains = <&CPU_PD0>;
> > > -			power-domain-names = "psci";
> > > +			power-domains = <&CPU_PD0>, <&rpmpd MSM8916_VDDMX_AO>;
> > > +			power-domain-names = "psci", "mx";
> > >  		};
> > >  
> > >  		CPU1: cpu@1 {
> > > @@ -122,8 +123,8 @@ CPU1: cpu@1 {
> > >  			cpu-supply = <&pm8916_spmi_s2>;
> > >  			operating-points-v2 = <&cpu_opp_table>;
> > >  			#cooling-cells = <2>;
> > > -			power-domains = <&CPU_PD1>;
> > > -			power-domain-names = "psci";
> > > +			power-domains = <&CPU_PD1>, <&rpmpd MSM8916_VDDMX_AO>;
> > > +			power-domain-names = "psci", "mx";
> > >  		};
> > >  
> > >  		CPU2: cpu@2 {
> > > @@ -136,8 +137,8 @@ CPU2: cpu@2 {
> > >  			cpu-supply = <&pm8916_spmi_s2>;
> > >  			operating-points-v2 = <&cpu_opp_table>;
> > >  			#cooling-cells = <2>;
> > > -			power-domains = <&CPU_PD2>;
> > > -			power-domain-names = "psci";
> > > +			power-domains = <&CPU_PD2>, <&rpmpd MSM8916_VDDMX_AO>;
> > > +			power-domain-names = "psci", "mx";
> > >  		};
> > >  
> > >  		CPU3: cpu@3 {
> > > @@ -150,8 +151,8 @@ CPU3: cpu@3 {
> > >  			cpu-supply = <&pm8916_spmi_s2>;
> > >  			operating-points-v2 = <&cpu_opp_table>;
> > >  			#cooling-cells = <2>;
> > > -			power-domains = <&CPU_PD3>;
> > > -			power-domain-names = "psci";
> > > +			power-domains = <&CPU_PD3>, <&rpmpd MSM8916_VDDMX_AO>;
> > > +			power-domain-names = "psci", "mx";
> > >  		};
> > >  
> > >  		L2_0: l2-cache {
> > > @@ -343,40 +344,52 @@ modem_alert0: trip-point@0 {
> > >  	};
> > >  
> > >  	cpu_opp_table: cpu_opp_table {
> > > -		compatible = "operating-points-v2";
> > > +		/*
> > > +		 * FIXME: The naming here is really weird, since MSM8916 does
> > > +		 * not have kyro. Maybe we should add a more generic compatible?
> > > +		 */
> > > +		compatible = "operating-points-v2-kryo-cpu";
> > >  		opp-shared;
> > >  
> > >  		opp-200000000 {
> > >  			opp-hz = /bits/ 64 <200000000>;
> > >  			opp-microvolt = <1050000>;
> > > +			required-opps = <&rpmpd_opp_svs_soc>;
> > >  		};
> > >  		opp-400000000 {
> > >  			opp-hz = /bits/ 64 <400000000>;
> > >  			opp-microvolt = <1050000>;
> > > +			required-opps = <&rpmpd_opp_svs_soc>;
> > >  		};
> > >  		opp-533330000 {
> > >  			opp-hz = /bits/ 64 <533330000>;
> > >  			opp-microvolt = <1150000>;
> > > +			required-opps = <&rpmpd_opp_nom>;
> > >  		};
> > >  		opp-800000000 {
> > >  			opp-hz = /bits/ 64 <800000000>;
> > >  			opp-microvolt = <1150000>;
> > > +			required-opps = <&rpmpd_opp_nom>;
> > >  		};
> > >  		opp-998400000 {
> > >  			opp-hz = /bits/ 64 <998400000>;
> > >  			opp-microvolt = <1350000>;
> > > +			required-opps = <&rpmpd_opp_super_turbo>;
> > >  		};
> > >  		opp-1094400000 {
> > >  			opp-hz = /bits/ 64 <1094400000>;
> > >  			opp-microvolt = <1350000>;
> > > +			required-opps = <&rpmpd_opp_super_turbo>;
> > >  		};
> > >  		opp-1152000000 {
> > >  			opp-hz = /bits/ 64 <1152000000>;
> > >  			opp-microvolt = <1350000>;
> > > +			required-opps = <&rpmpd_opp_super_turbo>;
> > >  		};
> > >  		opp-1209600000 {
> > >  			opp-hz = /bits/ 64 <1209600000>;
> > >  			opp-microvolt = <1350000>;
> > > +			required-opps = <&rpmpd_opp_super_turbo>;
> > >  		};
> > >  	};
> > >  
> > > @@ -1710,6 +1723,40 @@ rpmcc: qcom,rpmcc {
> > >  					#clock-cells = <1>;
> > >  				};
> > >  
> > > +				rpmpd: power-controller {
> > > +					compatible = "qcom,msm8916-rpmpd";
> > > +					#power-domain-cells = <1>;
> > > +					operating-points-v2 = <&rpmpd_opp_table>;
> > > +
> > > +					rpmpd_opp_table: opp-table {
> > > +						compatible = "operating-points-v2";
> > > +
> > > +						rpmpd_opp_ret: opp1 {
> > > +							opp-level = <1>;
> > > +						};
> > > +
> > > +						rpmpd_opp_svs: opp2 {
> > > +							opp-level = <2>;
> > > +						};
> > > +
> > > +						rpmpd_opp_svs_soc: opp3 {
> > > +							opp-level = <3>;
> > > +						};
> > > +
> > > +						rpmpd_opp_nom: opp4 {
> > > +							opp-level = <4>;
> > > +						};
> > > +
> > > +						rpmpd_opp_turbo: opp5 {
> > > +							opp-level = <5>;
> > > +						};
> > > +
> > > +						rpmpd_opp_super_turbo: opp6 {
> > > +							opp-level = <6>;
> > > +						};
> > > +					};
> > > +				};
> > > +
> > >  				smd_rpm_regulators: pm8916-regulators {
> > >  					compatible = "qcom,rpm-pm8916-regulators";
> > >  
> > > diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
> > > index f2ae9cd455c1..b0f6bd0fffc1 100644
> > > --- a/drivers/cpufreq/cpufreq-dt-platdev.c
> > > +++ b/drivers/cpufreq/cpufreq-dt-platdev.c
> > > @@ -128,6 +128,7 @@ static const struct of_device_id blacklist[] __initconst = {
> > >  	{ .compatible = "nvidia,tegra210", },
> > >  
> > >  	{ .compatible = "qcom,apq8096", },
> > > +	{ .compatible = "qcom,msm8916", },
> > >  	{ .compatible = "qcom,msm8996", },
> > >  	{ .compatible = "qcom,qcs404", },
> > >  
> > > diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > > index f0d2d5035413..c77a30349d08 100644
> > > --- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > > +++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > > @@ -129,6 +129,16 @@ static const struct qcom_cpufreq_match_data match_data_kryo = {
> > >  	.get_version = qcom_cpufreq_kryo_name_version,
> > >  };
> > >  
> > > +static const char *msm8916_genpd_names[] = { "mx", NULL };
> > > +
> > > +static const struct qcom_cpufreq_match_data match_data_msm8916 = {
> > > +	/*
> > > +	 * FIXME: Might need to implement .get_version here to handle
> > > +	 * different frequencies depending on speedbin/pvs version.
> > > +	 */
> > > +	.genpd_names = msm8916_genpd_names,
> > > +};
> > > +
> > >  static const char *qcs404_genpd_names[] = { "cpr", NULL };
> > >  
> > >  static const struct qcom_cpufreq_match_data match_data_qcs404 = {
> > > @@ -301,6 +311,7 @@ static struct platform_driver qcom_cpufreq_driver = {
> > >  
> > >  static const struct of_device_id qcom_cpufreq_match_list[] __initconst = {
> > >  	{ .compatible = "qcom,apq8096", .data = &match_data_kryo },
> > > +	{ .compatible = "qcom,msm8916", .data = &match_data_msm8916 },
> > >  	{ .compatible = "qcom,msm8996", .data = &match_data_kryo },
> > >  	{ .compatible = "qcom,qcs404", .data = &match_data_qcs404 },
> > >  	{},
> > > diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c
> > > index 2b1834c5609a..192ba9099964 100644
> > > --- a/drivers/soc/qcom/rpmpd.c
> > > +++ b/drivers/soc/qcom/rpmpd.c
> > > @@ -115,6 +115,26 @@ struct rpmpd_desc {
> > >  
> > >  static DEFINE_MUTEX(rpmpd_lock);
> > >  
> > > +/* msm8916 RPM Power Domains */
> > > +DEFINE_RPMPD_PAIR(msm8916, vddcx, vddcx_ao, SMPA, CORNER, 1);
> > > +DEFINE_RPMPD_PAIR(msm8916, vddmx, vddmx_ao, LDOA, CORNER, 3);
> > > +
> > > +DEFINE_RPMPD_VFC(msm8916, vddcx_vfc, SMPA, 1);
> > > +
> > > +static struct rpmpd *msm8916_rpmpds[] = {
> > > +	[MSM8916_VDDCX] =	&msm8916_vddcx,
> > > +	[MSM8916_VDDCX_AO] =	&msm8916_vddcx_ao,
> > > +	[MSM8916_VDDCX_VFC] =	&msm8916_vddcx_vfc,
> > > +	[MSM8916_VDDMX] =	&msm8916_vddmx,
> > > +	[MSM8916_VDDMX_AO] =	&msm8916_vddmx_ao,
> > > +};
> > > +
> > > +static const struct rpmpd_desc msm8916_desc = {
> > > +	.rpmpds = msm8916_rpmpds,
> > > +	.num_pds = ARRAY_SIZE(msm8916_rpmpds),
> > > +	.max_state = MAX_8996_RPMPD_STATE,
> > > +};
> > > +
> > >  /* msm8976 RPM Power Domains */
> > >  DEFINE_RPMPD_PAIR(msm8976, vddcx, vddcx_ao, SMPA, LEVEL, 2);
> > >  DEFINE_RPMPD_PAIR(msm8976, vddmx, vddmx_ao, SMPA, LEVEL, 6);
> > > @@ -220,6 +240,7 @@ static const struct rpmpd_desc qcs404_desc = {
> > >  };
> > >  
> > >  static const struct of_device_id rpmpd_match_table[] = {
> > > +	{ .compatible = "qcom,msm8916-rpmpd", .data = &msm8916_desc },
> > >  	{ .compatible = "qcom,msm8976-rpmpd", .data = &msm8976_desc },
> > >  	{ .compatible = "qcom,msm8996-rpmpd", .data = &msm8996_desc },
> > >  	{ .compatible = "qcom,msm8998-rpmpd", .data = &msm8998_desc },
> > > diff --git a/include/dt-bindings/power/qcom-rpmpd.h b/include/dt-bindings/power/qcom-rpmpd.h
> > > index 3f74096d5a7c..70d304a2deae 100644
> > > --- a/include/dt-bindings/power/qcom-rpmpd.h
> > > +++ b/include/dt-bindings/power/qcom-rpmpd.h
> > > @@ -51,6 +51,13 @@
> > >  #define RPMH_REGULATOR_LEVEL_TURBO	384
> > >  #define RPMH_REGULATOR_LEVEL_TURBO_L1	416
> > >  
> > > +/* MSM8916 Power Domain Indexes */
> > > +#define MSM8916_VDDCX		0
> > > +#define MSM8916_VDDCX_AO	1
> > > +#define MSM8916_VDDCX_VFC	2
> > > +#define MSM8916_VDDMX		3
> > > +#define MSM8916_VDDMX_AO	4
> > > +
> > >  /* MSM8976 Power Domain Indexes */
> > >  #define MSM8976_VDDCX		0
> > >  #define MSM8976_VDDCX_AO	1

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps
  2020-05-06 21:18             ` Stephan Gerhold
@ 2020-05-07  5:34               ` Bjorn Andersson
  2020-05-08 12:08                 ` Ulf Hansson
  2020-05-07 10:46               ` Stephan Gerhold
  1 sibling, 1 reply; 32+ messages in thread
From: Bjorn Andersson @ 2020-05-07  5:34 UTC (permalink / raw)
  To: Stephan Gerhold, Viresh Kumar, Ulf Hansson
  Cc: Loic Poulain, agross, linux-arm-msm

On Wed 06 May 14:18 PDT 2020, Stephan Gerhold wrote:

Viresh, Ulf,

Stephan is trying to describe the relationship between the CPU rail and
the memory rail on db410c (where the performance state of the memory
rail needs to be kept above the performance state of the CPU supply.

The latter is modelled as a power-domain and the performance state
changes as expected, but no one enables the power-domain.

What's the appropriate method for ensuring the power-domain is
enabled/disabled as needed? Should it be referenced in the hierarchical
power domain for the CPUs perhaps?

Regards,
Bjorn

> Hi,
> 
> On Sun, Apr 26, 2020 at 02:31:48PM +0200, Stephan Gerhold wrote:
> > On Wed, Apr 22, 2020 at 09:55:06PM -0700, Bjorn Andersson wrote:
> > > On Fri 03 Apr 11:00 PDT 2020, Stephan Gerhold wrote:
> > > 
> > > > On Fri, Apr 03, 2020 at 12:09:25PM +0200, Stephan Gerhold wrote:
> > > > > On Thu, Apr 02, 2020 at 06:31:19PM -0700, Bjorn Andersson wrote:
> > > > > > On Thu 02 Apr 01:13 PDT 2020, Stephan Gerhold wrote:
> > > > > > 
> > > > > > > Hi,
> > > > > > > 
> > > > > > > On Wed, Apr 01, 2020 at 07:50:59PM +0200, Loic Poulain wrote:
> > > > > > > > The highest cpu frequency opps have been dropped because CPR is not
> > > > > > > > supported. However, we can simply specify operating voltage so that
> > > > > > > > they match the max corner voltages for each freq. With that, we can
> > > > > > > > support up to 1.36Ghz. Ideally, msm8916 CPR should be implemented to
> > > > > > > > fine tune operating voltages and optimize power consumption.
> > > > > > > 
> > > > > > > Thanks for the patch! I was wondering how to enable the higher CPU
> > > > > > > frequencies for a while now...
> > > > > > > 
> > > > > > > I was actually quite excited to see CPR being mainlined for QCS404.
> > > > > > > If we are trying to add such a workaround (rather than CPR) for MSM8916
> > > > > > > now, does that mean it's unlikely to see CPR working for MSM8916
> > > > > > > anytime soon?
> > > > > > > 
> > > > > > > AFAICT, there is a WIP branch from Niklas Cassel here:
> > > > > > > https://git.linaro.org/people/nicolas.dechesne/niklas.cassel/kernel.git/log/?h=cpr-msm8916-mainline
> > > > > > > but it hasn't been updated for a while. (Not sure if it was working
> > > > > > > already...)
> > > > > > > 
> > > > > > > Can someone explain what is missing to make CPR work for MSM8916?
> > > > > > > 
> > > > > > 
> > > > > > CPR needs to control 3 things; VDD_APC, VDD_MX and MEMACC. On QCS404 it
> > > > > > seems we don't have to adjust VDD_MX, so the code for this is missing
> > > > > > from the driver.
> > > > > > 
> > > > > > So, afaict, what's missing is that rpmpd.c needs to gain support for
> > > > > > 8916, then the CPR driver needs to gain a cpr_acc_desc and compatible
> > > > > > for 8916, it needs to reference the VDDMX power domain and before/after
> > > > > > we're adjusting the corner of the CPR we need to adjust the MX according
> > > > > > to the mapping specified in the downstream kernel (i.e.  1->4, 2->5 and
> > > > > > 3->7).
> > > > > > 
> > > > > > 
> > > > > > Unfortunately, the requirement that VDDMX (VDD_MEM I presume) must be
> > > > > > higher than VDD_APC most likely needs to be taken into consideration for
> > > > > > Loic's proposed static voltage scaling as well. Unless VDD_MEM is left
> > > > > > in Turbo mode from the boot loader I think we need to take VDDMX to
> > > > > > corner 7 for speeds 998MHz and above (i.e. where we pull VDD_APC to
> > > > > > 1.35V).
> > > > > > 
> > > > > 
> > > > > I see! I wonder how hard it would be to add MSM8916 to rpmpd,
> > > > > looking at previous commits it's mainly setting up a few defines?
> > > > > 
> > > > > If I understand it correctly, the OPPs from rpmpd could then be
> > > > > referenced as "required-opps" in the CPU OPP table so that VDD_MX is
> > > > > scaled together with the CPU frequency, and doesn't need to stay at
> > > > > turbo mode (like in v3 from Loic) the whole time.
> > > > > 
> > > > 
> > > > I have been thinking about this some more and I think I came up with
> > > > some changes that make sense (but not entirely sure).
> > > > 
> > > > Based on the available downstream sources I guessed the defines to add
> > > > for MSM8916 to the rpmpd driver. Then I added the VDD_MX OPPs as
> > > > "required-opps" to the CPU OPP table so it would vote for the appopriate
> > > > corners (with the mapping you mentioned above).
> > > > 
> > > 
> > > I was not aware it was possible to describe the dependency between the
> > > CPU opp table and MX in this fashion. If that's the case then this looks
> > > really good and it should be straight forward to add MSM8916 support to
> > > the CPR driver as well.
> > > 
> > 
> > Indeed!
> > 
> > > > I haven't tested it yet, maybe I can get some feedback first if the code
> > > > seems reasonable or if I'm missing something obvious? :)
> > > > 
> > > 
> > > Have you tested this yet?
> > > 
> > 
> > I just did. It does not fully work, yet:
> > 
> > rpmpd_set_performance() is indeed called as necessary when switching the
> > CPU frequency. When I set 200 MHz it sets corner 3, with 533 MHz corner 4
> > and starting with 998 MHz corner 6. So far so good :)
> > 
> > However, there is never actually anything sent to the RPM. :(
> > It bails out in rpmpd_set_performance() before calling rpmpd_aggregate_corner():
> > 
> > 	/* Always send updates for vfc and vfl */
> > 	if (!pd->enabled && pd->key != KEY_FLOOR_CORNER &&
> > 	    pd->key != KEY_FLOOR_LEVEL)
> > 		goto out;
> > 
> > Seems like we just try to set performance states, but never actually
> > enable (rpmpd_power_on()) the power domain (pd->enabled == false).
> > 
> > I'm not sure which of the components involved here should handle that.
> > The OPP core when setting required OPPs, the genpd core etc.
> >
> > Any ideas?
> > 
> > Thanks,
> > Stephan
> > 
> 
> For now I have added something to qcom-cpufreq-nvmem.c to power on/enable
> the power domain (not really sure if it belongs there...):
> 
> diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> index a1b8238872a2..ed352ead037e 100644
> --- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
> +++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> @@ -26,6 +26,7 @@
>  #include <linux/platform_device.h>
>  #include <linux/pm_domain.h>
>  #include <linux/pm_opp.h>
> +#include <linux/pm_runtime.h>
>  #include <linux/slab.h>
>  #include <linux/soc/qcom/smem.h>
>  
> @@ -370,10 +371,13 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
>  		}
>  
>  		if (drv->data->genpd_names) {
> +			struct device **pd_dev;
> +			const char **name = drv->data->genpd_names;
> +
>  			drv->genpd_opp_tables[cpu] =
>  				dev_pm_opp_attach_genpd(cpu_dev,
>  							drv->data->genpd_names,
> -							NULL);
> +							&pd_dev);
>  			if (IS_ERR(drv->genpd_opp_tables[cpu])) {
>  				ret = PTR_ERR(drv->genpd_opp_tables[cpu]);
>  				if (ret != -EPROBE_DEFER)
> @@ -382,6 +386,12 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
>  						ret);
>  				goto free_genpd_opp;
>  			}
> +
> +			while (*name) {
> +				pm_runtime_get_sync(*pd_dev);
> +				name++;
> +				pd_dev++;
> +			}
>  		}
>  	}
> 
> I really wonder why this doesn't affect CPR (or does it?).
> So far I was not able to find anything that would power on/enable
> the "cpr" power domain either. But I don't have a qcs404 to verify.
>  
> As far as I can tell from the log, the corner votes are correctly sent
> to the RPM now when the CPU frequency is changed.
> 
> However...
> 
> > > > Also: Is there a good way to validate these changes?
> > > > I suppose I could check the genpd state but that wouldn't tell me if the
> > > > corner was applied correctly. Maybe I can check the actual voltage
> > > > through the SPMI interface, hm...
> > > > 
> > > 
> > > Validating that S2 and VDD_MX changes appropriately in Linux would be a
> > > pretty good test.
> > > 
> 
> Unfortunately I was not able to see any change in the voltage of L3 yet.
> On samsung-a5u, /sys/class/regulator/<l3 spmi regulator>/microvolts
> permanently reports 1300000 uV, even after a few different corner votes.
> 
> I'm not sure if:
> 
>   - This is normal (maybe some other remoteproc has a higher vote?)
>     - I tried to disable wcnss, venus and hexagon without difference
> 
>   - I'm just missing something in the code
> 
>   - This is some peculiarity of the RPM firmware on samsung-a5u.
>     (Although that seems quite unlikely to me...)
> 
> Any ideas? :/
> 
> Thanks,
> Stephan
> 
> > > > If this seems like a good approach I can split up the changes in
> > > > reasonable patches and post it separately. For now the full diff below.
> > > > 
> > > 
> > > Please do
> > > 
> > > Regards,
> > > Bjorn
> > > 
> > > > Stephan
> > > > 
> > > >  arch/arm64/boot/dts/qcom/msm8916.dtsi  | 65 +++++++++++++++++++++++++++++-----
> > > >  drivers/cpufreq/cpufreq-dt-platdev.c   |  1 +
> > > >  drivers/cpufreq/qcom-cpufreq-nvmem.c   | 11 ++++++
> > > >  drivers/soc/qcom/rpmpd.c               | 21 +++++++++++
> > > >  include/dt-bindings/power/qcom-rpmpd.h |  7 ++++
> > > >  5 files changed, 96 insertions(+), 9 deletions(-)
> > > > 
> > > > diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > > > index b0a82447976a..5b8fce8609d0 100644
> > > > --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > > > +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > > > @@ -10,6 +10,7 @@
> > > >  #include <dt-bindings/soc/qcom,apr.h>
> > > >  #include <dt-bindings/sound/qcom,q6afe.h>
> > > >  #include <dt-bindings/thermal/thermal.h>
> > > > +#include <dt-bindings/power/qcom-rpmpd.h>
> > > >  
> > > >  / {
> > > >  	interrupt-parent = <&intc>;
> > > > @@ -108,8 +109,8 @@ CPU0: cpu@0 {
> > > >  			cpu-supply = <&pm8916_spmi_s2>;
> > > >  			operating-points-v2 = <&cpu_opp_table>;
> > > >  			#cooling-cells = <2>;
> > > > -			power-domains = <&CPU_PD0>;
> > > > -			power-domain-names = "psci";
> > > > +			power-domains = <&CPU_PD0>, <&rpmpd MSM8916_VDDMX_AO>;
> > > > +			power-domain-names = "psci", "mx";
> > > >  		};
> > > >  
> > > >  		CPU1: cpu@1 {
> > > > @@ -122,8 +123,8 @@ CPU1: cpu@1 {
> > > >  			cpu-supply = <&pm8916_spmi_s2>;
> > > >  			operating-points-v2 = <&cpu_opp_table>;
> > > >  			#cooling-cells = <2>;
> > > > -			power-domains = <&CPU_PD1>;
> > > > -			power-domain-names = "psci";
> > > > +			power-domains = <&CPU_PD1>, <&rpmpd MSM8916_VDDMX_AO>;
> > > > +			power-domain-names = "psci", "mx";
> > > >  		};
> > > >  
> > > >  		CPU2: cpu@2 {
> > > > @@ -136,8 +137,8 @@ CPU2: cpu@2 {
> > > >  			cpu-supply = <&pm8916_spmi_s2>;
> > > >  			operating-points-v2 = <&cpu_opp_table>;
> > > >  			#cooling-cells = <2>;
> > > > -			power-domains = <&CPU_PD2>;
> > > > -			power-domain-names = "psci";
> > > > +			power-domains = <&CPU_PD2>, <&rpmpd MSM8916_VDDMX_AO>;
> > > > +			power-domain-names = "psci", "mx";
> > > >  		};
> > > >  
> > > >  		CPU3: cpu@3 {
> > > > @@ -150,8 +151,8 @@ CPU3: cpu@3 {
> > > >  			cpu-supply = <&pm8916_spmi_s2>;
> > > >  			operating-points-v2 = <&cpu_opp_table>;
> > > >  			#cooling-cells = <2>;
> > > > -			power-domains = <&CPU_PD3>;
> > > > -			power-domain-names = "psci";
> > > > +			power-domains = <&CPU_PD3>, <&rpmpd MSM8916_VDDMX_AO>;
> > > > +			power-domain-names = "psci", "mx";
> > > >  		};
> > > >  
> > > >  		L2_0: l2-cache {
> > > > @@ -343,40 +344,52 @@ modem_alert0: trip-point@0 {
> > > >  	};
> > > >  
> > > >  	cpu_opp_table: cpu_opp_table {
> > > > -		compatible = "operating-points-v2";
> > > > +		/*
> > > > +		 * FIXME: The naming here is really weird, since MSM8916 does
> > > > +		 * not have kyro. Maybe we should add a more generic compatible?
> > > > +		 */
> > > > +		compatible = "operating-points-v2-kryo-cpu";
> > > >  		opp-shared;
> > > >  
> > > >  		opp-200000000 {
> > > >  			opp-hz = /bits/ 64 <200000000>;
> > > >  			opp-microvolt = <1050000>;
> > > > +			required-opps = <&rpmpd_opp_svs_soc>;
> > > >  		};
> > > >  		opp-400000000 {
> > > >  			opp-hz = /bits/ 64 <400000000>;
> > > >  			opp-microvolt = <1050000>;
> > > > +			required-opps = <&rpmpd_opp_svs_soc>;
> > > >  		};
> > > >  		opp-533330000 {
> > > >  			opp-hz = /bits/ 64 <533330000>;
> > > >  			opp-microvolt = <1150000>;
> > > > +			required-opps = <&rpmpd_opp_nom>;
> > > >  		};
> > > >  		opp-800000000 {
> > > >  			opp-hz = /bits/ 64 <800000000>;
> > > >  			opp-microvolt = <1150000>;
> > > > +			required-opps = <&rpmpd_opp_nom>;
> > > >  		};
> > > >  		opp-998400000 {
> > > >  			opp-hz = /bits/ 64 <998400000>;
> > > >  			opp-microvolt = <1350000>;
> > > > +			required-opps = <&rpmpd_opp_super_turbo>;
> > > >  		};
> > > >  		opp-1094400000 {
> > > >  			opp-hz = /bits/ 64 <1094400000>;
> > > >  			opp-microvolt = <1350000>;
> > > > +			required-opps = <&rpmpd_opp_super_turbo>;
> > > >  		};
> > > >  		opp-1152000000 {
> > > >  			opp-hz = /bits/ 64 <1152000000>;
> > > >  			opp-microvolt = <1350000>;
> > > > +			required-opps = <&rpmpd_opp_super_turbo>;
> > > >  		};
> > > >  		opp-1209600000 {
> > > >  			opp-hz = /bits/ 64 <1209600000>;
> > > >  			opp-microvolt = <1350000>;
> > > > +			required-opps = <&rpmpd_opp_super_turbo>;
> > > >  		};
> > > >  	};
> > > >  
> > > > @@ -1710,6 +1723,40 @@ rpmcc: qcom,rpmcc {
> > > >  					#clock-cells = <1>;
> > > >  				};
> > > >  
> > > > +				rpmpd: power-controller {
> > > > +					compatible = "qcom,msm8916-rpmpd";
> > > > +					#power-domain-cells = <1>;
> > > > +					operating-points-v2 = <&rpmpd_opp_table>;
> > > > +
> > > > +					rpmpd_opp_table: opp-table {
> > > > +						compatible = "operating-points-v2";
> > > > +
> > > > +						rpmpd_opp_ret: opp1 {
> > > > +							opp-level = <1>;
> > > > +						};
> > > > +
> > > > +						rpmpd_opp_svs: opp2 {
> > > > +							opp-level = <2>;
> > > > +						};
> > > > +
> > > > +						rpmpd_opp_svs_soc: opp3 {
> > > > +							opp-level = <3>;
> > > > +						};
> > > > +
> > > > +						rpmpd_opp_nom: opp4 {
> > > > +							opp-level = <4>;
> > > > +						};
> > > > +
> > > > +						rpmpd_opp_turbo: opp5 {
> > > > +							opp-level = <5>;
> > > > +						};
> > > > +
> > > > +						rpmpd_opp_super_turbo: opp6 {
> > > > +							opp-level = <6>;
> > > > +						};
> > > > +					};
> > > > +				};
> > > > +
> > > >  				smd_rpm_regulators: pm8916-regulators {
> > > >  					compatible = "qcom,rpm-pm8916-regulators";
> > > >  
> > > > diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
> > > > index f2ae9cd455c1..b0f6bd0fffc1 100644
> > > > --- a/drivers/cpufreq/cpufreq-dt-platdev.c
> > > > +++ b/drivers/cpufreq/cpufreq-dt-platdev.c
> > > > @@ -128,6 +128,7 @@ static const struct of_device_id blacklist[] __initconst = {
> > > >  	{ .compatible = "nvidia,tegra210", },
> > > >  
> > > >  	{ .compatible = "qcom,apq8096", },
> > > > +	{ .compatible = "qcom,msm8916", },
> > > >  	{ .compatible = "qcom,msm8996", },
> > > >  	{ .compatible = "qcom,qcs404", },
> > > >  
> > > > diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > > > index f0d2d5035413..c77a30349d08 100644
> > > > --- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > > > +++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > > > @@ -129,6 +129,16 @@ static const struct qcom_cpufreq_match_data match_data_kryo = {
> > > >  	.get_version = qcom_cpufreq_kryo_name_version,
> > > >  };
> > > >  
> > > > +static const char *msm8916_genpd_names[] = { "mx", NULL };
> > > > +
> > > > +static const struct qcom_cpufreq_match_data match_data_msm8916 = {
> > > > +	/*
> > > > +	 * FIXME: Might need to implement .get_version here to handle
> > > > +	 * different frequencies depending on speedbin/pvs version.
> > > > +	 */
> > > > +	.genpd_names = msm8916_genpd_names,
> > > > +};
> > > > +
> > > >  static const char *qcs404_genpd_names[] = { "cpr", NULL };
> > > >  
> > > >  static const struct qcom_cpufreq_match_data match_data_qcs404 = {
> > > > @@ -301,6 +311,7 @@ static struct platform_driver qcom_cpufreq_driver = {
> > > >  
> > > >  static const struct of_device_id qcom_cpufreq_match_list[] __initconst = {
> > > >  	{ .compatible = "qcom,apq8096", .data = &match_data_kryo },
> > > > +	{ .compatible = "qcom,msm8916", .data = &match_data_msm8916 },
> > > >  	{ .compatible = "qcom,msm8996", .data = &match_data_kryo },
> > > >  	{ .compatible = "qcom,qcs404", .data = &match_data_qcs404 },
> > > >  	{},
> > > > diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c
> > > > index 2b1834c5609a..192ba9099964 100644
> > > > --- a/drivers/soc/qcom/rpmpd.c
> > > > +++ b/drivers/soc/qcom/rpmpd.c
> > > > @@ -115,6 +115,26 @@ struct rpmpd_desc {
> > > >  
> > > >  static DEFINE_MUTEX(rpmpd_lock);
> > > >  
> > > > +/* msm8916 RPM Power Domains */
> > > > +DEFINE_RPMPD_PAIR(msm8916, vddcx, vddcx_ao, SMPA, CORNER, 1);
> > > > +DEFINE_RPMPD_PAIR(msm8916, vddmx, vddmx_ao, LDOA, CORNER, 3);
> > > > +
> > > > +DEFINE_RPMPD_VFC(msm8916, vddcx_vfc, SMPA, 1);
> > > > +
> > > > +static struct rpmpd *msm8916_rpmpds[] = {
> > > > +	[MSM8916_VDDCX] =	&msm8916_vddcx,
> > > > +	[MSM8916_VDDCX_AO] =	&msm8916_vddcx_ao,
> > > > +	[MSM8916_VDDCX_VFC] =	&msm8916_vddcx_vfc,
> > > > +	[MSM8916_VDDMX] =	&msm8916_vddmx,
> > > > +	[MSM8916_VDDMX_AO] =	&msm8916_vddmx_ao,
> > > > +};
> > > > +
> > > > +static const struct rpmpd_desc msm8916_desc = {
> > > > +	.rpmpds = msm8916_rpmpds,
> > > > +	.num_pds = ARRAY_SIZE(msm8916_rpmpds),
> > > > +	.max_state = MAX_8996_RPMPD_STATE,
> > > > +};
> > > > +
> > > >  /* msm8976 RPM Power Domains */
> > > >  DEFINE_RPMPD_PAIR(msm8976, vddcx, vddcx_ao, SMPA, LEVEL, 2);
> > > >  DEFINE_RPMPD_PAIR(msm8976, vddmx, vddmx_ao, SMPA, LEVEL, 6);
> > > > @@ -220,6 +240,7 @@ static const struct rpmpd_desc qcs404_desc = {
> > > >  };
> > > >  
> > > >  static const struct of_device_id rpmpd_match_table[] = {
> > > > +	{ .compatible = "qcom,msm8916-rpmpd", .data = &msm8916_desc },
> > > >  	{ .compatible = "qcom,msm8976-rpmpd", .data = &msm8976_desc },
> > > >  	{ .compatible = "qcom,msm8996-rpmpd", .data = &msm8996_desc },
> > > >  	{ .compatible = "qcom,msm8998-rpmpd", .data = &msm8998_desc },
> > > > diff --git a/include/dt-bindings/power/qcom-rpmpd.h b/include/dt-bindings/power/qcom-rpmpd.h
> > > > index 3f74096d5a7c..70d304a2deae 100644
> > > > --- a/include/dt-bindings/power/qcom-rpmpd.h
> > > > +++ b/include/dt-bindings/power/qcom-rpmpd.h
> > > > @@ -51,6 +51,13 @@
> > > >  #define RPMH_REGULATOR_LEVEL_TURBO	384
> > > >  #define RPMH_REGULATOR_LEVEL_TURBO_L1	416
> > > >  
> > > > +/* MSM8916 Power Domain Indexes */
> > > > +#define MSM8916_VDDCX		0
> > > > +#define MSM8916_VDDCX_AO	1
> > > > +#define MSM8916_VDDCX_VFC	2
> > > > +#define MSM8916_VDDMX		3
> > > > +#define MSM8916_VDDMX_AO	4
> > > > +
> > > >  /* MSM8976 Power Domain Indexes */
> > > >  #define MSM8976_VDDCX		0
> > > >  #define MSM8976_VDDCX_AO	1

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps
  2020-05-06 21:18             ` Stephan Gerhold
  2020-05-07  5:34               ` Bjorn Andersson
@ 2020-05-07 10:46               ` Stephan Gerhold
  2020-05-21 19:18                 ` Stephan Gerhold
  1 sibling, 1 reply; 32+ messages in thread
From: Stephan Gerhold @ 2020-05-07 10:46 UTC (permalink / raw)
  To: Bjorn Andersson; +Cc: Loic Poulain, agross, linux-arm-msm


[-- Attachment #1: Type: text/plain, Size: 19475 bytes --]

On Wed, May 06, 2020 at 11:18:07PM +0200, Stephan Gerhold wrote:
> Hi,
> 
> On Sun, Apr 26, 2020 at 02:31:48PM +0200, Stephan Gerhold wrote:
> > On Wed, Apr 22, 2020 at 09:55:06PM -0700, Bjorn Andersson wrote:
> > > On Fri 03 Apr 11:00 PDT 2020, Stephan Gerhold wrote:
> > > 
> > > > On Fri, Apr 03, 2020 at 12:09:25PM +0200, Stephan Gerhold wrote:
> > > > > On Thu, Apr 02, 2020 at 06:31:19PM -0700, Bjorn Andersson wrote:
> > > > > > On Thu 02 Apr 01:13 PDT 2020, Stephan Gerhold wrote:
> > > > > > 
> > > > > > > Hi,
> > > > > > > 
> > > > > > > On Wed, Apr 01, 2020 at 07:50:59PM +0200, Loic Poulain wrote:
> > > > > > > > The highest cpu frequency opps have been dropped because CPR is not
> > > > > > > > supported. However, we can simply specify operating voltage so that
> > > > > > > > they match the max corner voltages for each freq. With that, we can
> > > > > > > > support up to 1.36Ghz. Ideally, msm8916 CPR should be implemented to
> > > > > > > > fine tune operating voltages and optimize power consumption.
> > > > > > > 
> > > > > > > Thanks for the patch! I was wondering how to enable the higher CPU
> > > > > > > frequencies for a while now...
> > > > > > > 
> > > > > > > I was actually quite excited to see CPR being mainlined for QCS404.
> > > > > > > If we are trying to add such a workaround (rather than CPR) for MSM8916
> > > > > > > now, does that mean it's unlikely to see CPR working for MSM8916
> > > > > > > anytime soon?
> > > > > > > 
> > > > > > > AFAICT, there is a WIP branch from Niklas Cassel here:
> > > > > > > https://git.linaro.org/people/nicolas.dechesne/niklas.cassel/kernel.git/log/?h=cpr-msm8916-mainline
> > > > > > > but it hasn't been updated for a while. (Not sure if it was working
> > > > > > > already...)
> > > > > > > 
> > > > > > > Can someone explain what is missing to make CPR work for MSM8916?
> > > > > > > 
> > > > > > 
> > > > > > CPR needs to control 3 things; VDD_APC, VDD_MX and MEMACC. On QCS404 it
> > > > > > seems we don't have to adjust VDD_MX, so the code for this is missing
> > > > > > from the driver.
> > > > > > 
> > > > > > So, afaict, what's missing is that rpmpd.c needs to gain support for
> > > > > > 8916, then the CPR driver needs to gain a cpr_acc_desc and compatible
> > > > > > for 8916, it needs to reference the VDDMX power domain and before/after
> > > > > > we're adjusting the corner of the CPR we need to adjust the MX according
> > > > > > to the mapping specified in the downstream kernel (i.e.  1->4, 2->5 and
> > > > > > 3->7).
> > > > > > 
> > > > > > 
> > > > > > Unfortunately, the requirement that VDDMX (VDD_MEM I presume) must be
> > > > > > higher than VDD_APC most likely needs to be taken into consideration for
> > > > > > Loic's proposed static voltage scaling as well. Unless VDD_MEM is left
> > > > > > in Turbo mode from the boot loader I think we need to take VDDMX to
> > > > > > corner 7 for speeds 998MHz and above (i.e. where we pull VDD_APC to
> > > > > > 1.35V).
> > > > > > 
> > > > > 
> > > > > I see! I wonder how hard it would be to add MSM8916 to rpmpd,
> > > > > looking at previous commits it's mainly setting up a few defines?
> > > > > 
> > > > > If I understand it correctly, the OPPs from rpmpd could then be
> > > > > referenced as "required-opps" in the CPU OPP table so that VDD_MX is
> > > > > scaled together with the CPU frequency, and doesn't need to stay at
> > > > > turbo mode (like in v3 from Loic) the whole time.
> > > > > 
> > > > 
> > > > I have been thinking about this some more and I think I came up with
> > > > some changes that make sense (but not entirely sure).
> > > > 
> > > > Based on the available downstream sources I guessed the defines to add
> > > > for MSM8916 to the rpmpd driver. Then I added the VDD_MX OPPs as
> > > > "required-opps" to the CPU OPP table so it would vote for the appopriate
> > > > corners (with the mapping you mentioned above).
> > > > 
> > > 
> > > I was not aware it was possible to describe the dependency between the
> > > CPU opp table and MX in this fashion. If that's the case then this looks
> > > really good and it should be straight forward to add MSM8916 support to
> > > the CPR driver as well.
> > > 
> > 
> > Indeed!
> > 
> > > > I haven't tested it yet, maybe I can get some feedback first if the code
> > > > seems reasonable or if I'm missing something obvious? :)
> > > > 
> > > 
> > > Have you tested this yet?
> > > 
> > 
> > I just did. It does not fully work, yet:
> > 
> > rpmpd_set_performance() is indeed called as necessary when switching the
> > CPU frequency. When I set 200 MHz it sets corner 3, with 533 MHz corner 4
> > and starting with 998 MHz corner 6. So far so good :)
> > 
> > However, there is never actually anything sent to the RPM. :(
> > It bails out in rpmpd_set_performance() before calling rpmpd_aggregate_corner():
> > 
> > 	/* Always send updates for vfc and vfl */
> > 	if (!pd->enabled && pd->key != KEY_FLOOR_CORNER &&
> > 	    pd->key != KEY_FLOOR_LEVEL)
> > 		goto out;
> > 
> > Seems like we just try to set performance states, but never actually
> > enable (rpmpd_power_on()) the power domain (pd->enabled == false).
> > 
> > I'm not sure which of the components involved here should handle that.
> > The OPP core when setting required OPPs, the genpd core etc.
> >
> > Any ideas?
> > 
> > Thanks,
> > Stephan
> > 
> 
> For now I have added something to qcom-cpufreq-nvmem.c to power on/enable
> the power domain (not really sure if it belongs there...):
> 
> diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> index a1b8238872a2..ed352ead037e 100644
> --- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
> +++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> @@ -26,6 +26,7 @@
>  #include <linux/platform_device.h>
>  #include <linux/pm_domain.h>
>  #include <linux/pm_opp.h>
> +#include <linux/pm_runtime.h>
>  #include <linux/slab.h>
>  #include <linux/soc/qcom/smem.h>
>  
> @@ -370,10 +371,13 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
>  		}
>  
>  		if (drv->data->genpd_names) {
> +			struct device **pd_dev;
> +			const char **name = drv->data->genpd_names;
> +
>  			drv->genpd_opp_tables[cpu] =
>  				dev_pm_opp_attach_genpd(cpu_dev,
>  							drv->data->genpd_names,
> -							NULL);
> +							&pd_dev);
>  			if (IS_ERR(drv->genpd_opp_tables[cpu])) {
>  				ret = PTR_ERR(drv->genpd_opp_tables[cpu]);
>  				if (ret != -EPROBE_DEFER)
> @@ -382,6 +386,12 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
>  						ret);
>  				goto free_genpd_opp;
>  			}
> +
> +			while (*name) {
> +				pm_runtime_get_sync(*pd_dev);
> +				name++;
> +				pd_dev++;
> +			}
>  		}
>  	}
> 
> I really wonder why this doesn't affect CPR (or does it?).
> So far I was not able to find anything that would power on/enable
> the "cpr" power domain either. But I don't have a qcs404 to verify.
>  
> As far as I can tell from the log, the corner votes are correctly sent
> to the RPM now when the CPU frequency is changed.
> 
> However...
> 
> > > > Also: Is there a good way to validate these changes?
> > > > I suppose I could check the genpd state but that wouldn't tell me if the
> > > > corner was applied correctly. Maybe I can check the actual voltage
> > > > through the SPMI interface, hm...
> > > > 
> > > 
> > > Validating that S2 and VDD_MX changes appropriately in Linux would be a
> > > pretty good test.
> > > 
> 
> Unfortunately I was not able to see any change in the voltage of L3 yet.
> On samsung-a5u, /sys/class/regulator/<l3 spmi regulator>/microvolts
> permanently reports 1300000 uV, even after a few different corner votes.
> 
> I'm not sure if:
> 
>   - This is normal (maybe some other remoteproc has a higher vote?)
>     - I tried to disable wcnss, venus and hexagon without difference
> 
>   - I'm just missing something in the code
> 
>   - This is some peculiarity of the RPM firmware on samsung-a5u.
>     (Although that seems quite unlikely to me...)
> 
> Any ideas? :/
> 

I just tried the same on the downstream kernel for samsung-a5u.
There the L3 voltage doesn't change either, it stays on 1300000 uV
permanently. So more likely would be either "this is normal" or
"This is some peculiarity of the RPM firmware on samsung-a5u".

I don't have a DB410c available for testing, but I'm curious if it would
work correctly there. So far I have been unable to find any obvious
mistake in my changes.

I'm attaching the full diff (including Loic's changes) in case someone
wants to test this on the DB410c (or some other MSM8916 device).
Basically you need to:

  1. CONFIG_QCOM_RPMPD=y
     CONFIG_ARM_QCOM_CPUFREQ_NVMEM=y
  2. Run it and change CPU frequencies a bit
     (either with an automatic CPU governor, or by setting speeds
      manually with powersave/performance/userspace)
  3. There should be "set performance state" messages in dmesg
     for the VDD_MX corner votes
  4. Identify the spmi l3 regulator using /sys/class/regulator/*/name
  5. Check the reported voltage in /sys/class/regulator/.../microvolts

For me it stays on 1300000 uV, permanently. :(

Thanks,
Stephan

> > > > If this seems like a good approach I can split up the changes in
> > > > reasonable patches and post it separately. For now the full diff below.
> > > > 
> > > 
> > > Please do
> > > 
> > > Regards,
> > > Bjorn
> > > 
> > > > Stephan
> > > > 
> > > >  arch/arm64/boot/dts/qcom/msm8916.dtsi  | 65 +++++++++++++++++++++++++++++-----
> > > >  drivers/cpufreq/cpufreq-dt-platdev.c   |  1 +
> > > >  drivers/cpufreq/qcom-cpufreq-nvmem.c   | 11 ++++++
> > > >  drivers/soc/qcom/rpmpd.c               | 21 +++++++++++
> > > >  include/dt-bindings/power/qcom-rpmpd.h |  7 ++++
> > > >  5 files changed, 96 insertions(+), 9 deletions(-)
> > > > 
> > > > diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > > > index b0a82447976a..5b8fce8609d0 100644
> > > > --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > > > +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > > > @@ -10,6 +10,7 @@
> > > >  #include <dt-bindings/soc/qcom,apr.h>
> > > >  #include <dt-bindings/sound/qcom,q6afe.h>
> > > >  #include <dt-bindings/thermal/thermal.h>
> > > > +#include <dt-bindings/power/qcom-rpmpd.h>
> > > >  
> > > >  / {
> > > >  	interrupt-parent = <&intc>;
> > > > @@ -108,8 +109,8 @@ CPU0: cpu@0 {
> > > >  			cpu-supply = <&pm8916_spmi_s2>;
> > > >  			operating-points-v2 = <&cpu_opp_table>;
> > > >  			#cooling-cells = <2>;
> > > > -			power-domains = <&CPU_PD0>;
> > > > -			power-domain-names = "psci";
> > > > +			power-domains = <&CPU_PD0>, <&rpmpd MSM8916_VDDMX_AO>;
> > > > +			power-domain-names = "psci", "mx";
> > > >  		};
> > > >  
> > > >  		CPU1: cpu@1 {
> > > > @@ -122,8 +123,8 @@ CPU1: cpu@1 {
> > > >  			cpu-supply = <&pm8916_spmi_s2>;
> > > >  			operating-points-v2 = <&cpu_opp_table>;
> > > >  			#cooling-cells = <2>;
> > > > -			power-domains = <&CPU_PD1>;
> > > > -			power-domain-names = "psci";
> > > > +			power-domains = <&CPU_PD1>, <&rpmpd MSM8916_VDDMX_AO>;
> > > > +			power-domain-names = "psci", "mx";
> > > >  		};
> > > >  
> > > >  		CPU2: cpu@2 {
> > > > @@ -136,8 +137,8 @@ CPU2: cpu@2 {
> > > >  			cpu-supply = <&pm8916_spmi_s2>;
> > > >  			operating-points-v2 = <&cpu_opp_table>;
> > > >  			#cooling-cells = <2>;
> > > > -			power-domains = <&CPU_PD2>;
> > > > -			power-domain-names = "psci";
> > > > +			power-domains = <&CPU_PD2>, <&rpmpd MSM8916_VDDMX_AO>;
> > > > +			power-domain-names = "psci", "mx";
> > > >  		};
> > > >  
> > > >  		CPU3: cpu@3 {
> > > > @@ -150,8 +151,8 @@ CPU3: cpu@3 {
> > > >  			cpu-supply = <&pm8916_spmi_s2>;
> > > >  			operating-points-v2 = <&cpu_opp_table>;
> > > >  			#cooling-cells = <2>;
> > > > -			power-domains = <&CPU_PD3>;
> > > > -			power-domain-names = "psci";
> > > > +			power-domains = <&CPU_PD3>, <&rpmpd MSM8916_VDDMX_AO>;
> > > > +			power-domain-names = "psci", "mx";
> > > >  		};
> > > >  
> > > >  		L2_0: l2-cache {
> > > > @@ -343,40 +344,52 @@ modem_alert0: trip-point@0 {
> > > >  	};
> > > >  
> > > >  	cpu_opp_table: cpu_opp_table {
> > > > -		compatible = "operating-points-v2";
> > > > +		/*
> > > > +		 * FIXME: The naming here is really weird, since MSM8916 does
> > > > +		 * not have kyro. Maybe we should add a more generic compatible?
> > > > +		 */
> > > > +		compatible = "operating-points-v2-kryo-cpu";
> > > >  		opp-shared;
> > > >  
> > > >  		opp-200000000 {
> > > >  			opp-hz = /bits/ 64 <200000000>;
> > > >  			opp-microvolt = <1050000>;
> > > > +			required-opps = <&rpmpd_opp_svs_soc>;
> > > >  		};
> > > >  		opp-400000000 {
> > > >  			opp-hz = /bits/ 64 <400000000>;
> > > >  			opp-microvolt = <1050000>;
> > > > +			required-opps = <&rpmpd_opp_svs_soc>;
> > > >  		};
> > > >  		opp-533330000 {
> > > >  			opp-hz = /bits/ 64 <533330000>;
> > > >  			opp-microvolt = <1150000>;
> > > > +			required-opps = <&rpmpd_opp_nom>;
> > > >  		};
> > > >  		opp-800000000 {
> > > >  			opp-hz = /bits/ 64 <800000000>;
> > > >  			opp-microvolt = <1150000>;
> > > > +			required-opps = <&rpmpd_opp_nom>;
> > > >  		};
> > > >  		opp-998400000 {
> > > >  			opp-hz = /bits/ 64 <998400000>;
> > > >  			opp-microvolt = <1350000>;
> > > > +			required-opps = <&rpmpd_opp_super_turbo>;
> > > >  		};
> > > >  		opp-1094400000 {
> > > >  			opp-hz = /bits/ 64 <1094400000>;
> > > >  			opp-microvolt = <1350000>;
> > > > +			required-opps = <&rpmpd_opp_super_turbo>;
> > > >  		};
> > > >  		opp-1152000000 {
> > > >  			opp-hz = /bits/ 64 <1152000000>;
> > > >  			opp-microvolt = <1350000>;
> > > > +			required-opps = <&rpmpd_opp_super_turbo>;
> > > >  		};
> > > >  		opp-1209600000 {
> > > >  			opp-hz = /bits/ 64 <1209600000>;
> > > >  			opp-microvolt = <1350000>;
> > > > +			required-opps = <&rpmpd_opp_super_turbo>;
> > > >  		};
> > > >  	};
> > > >  
> > > > @@ -1710,6 +1723,40 @@ rpmcc: qcom,rpmcc {
> > > >  					#clock-cells = <1>;
> > > >  				};
> > > >  
> > > > +				rpmpd: power-controller {
> > > > +					compatible = "qcom,msm8916-rpmpd";
> > > > +					#power-domain-cells = <1>;
> > > > +					operating-points-v2 = <&rpmpd_opp_table>;
> > > > +
> > > > +					rpmpd_opp_table: opp-table {
> > > > +						compatible = "operating-points-v2";
> > > > +
> > > > +						rpmpd_opp_ret: opp1 {
> > > > +							opp-level = <1>;
> > > > +						};
> > > > +
> > > > +						rpmpd_opp_svs: opp2 {
> > > > +							opp-level = <2>;
> > > > +						};
> > > > +
> > > > +						rpmpd_opp_svs_soc: opp3 {
> > > > +							opp-level = <3>;
> > > > +						};
> > > > +
> > > > +						rpmpd_opp_nom: opp4 {
> > > > +							opp-level = <4>;
> > > > +						};
> > > > +
> > > > +						rpmpd_opp_turbo: opp5 {
> > > > +							opp-level = <5>;
> > > > +						};
> > > > +
> > > > +						rpmpd_opp_super_turbo: opp6 {
> > > > +							opp-level = <6>;
> > > > +						};
> > > > +					};
> > > > +				};
> > > > +
> > > >  				smd_rpm_regulators: pm8916-regulators {
> > > >  					compatible = "qcom,rpm-pm8916-regulators";
> > > >  
> > > > diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
> > > > index f2ae9cd455c1..b0f6bd0fffc1 100644
> > > > --- a/drivers/cpufreq/cpufreq-dt-platdev.c
> > > > +++ b/drivers/cpufreq/cpufreq-dt-platdev.c
> > > > @@ -128,6 +128,7 @@ static const struct of_device_id blacklist[] __initconst = {
> > > >  	{ .compatible = "nvidia,tegra210", },
> > > >  
> > > >  	{ .compatible = "qcom,apq8096", },
> > > > +	{ .compatible = "qcom,msm8916", },
> > > >  	{ .compatible = "qcom,msm8996", },
> > > >  	{ .compatible = "qcom,qcs404", },
> > > >  
> > > > diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > > > index f0d2d5035413..c77a30349d08 100644
> > > > --- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > > > +++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > > > @@ -129,6 +129,16 @@ static const struct qcom_cpufreq_match_data match_data_kryo = {
> > > >  	.get_version = qcom_cpufreq_kryo_name_version,
> > > >  };
> > > >  
> > > > +static const char *msm8916_genpd_names[] = { "mx", NULL };
> > > > +
> > > > +static const struct qcom_cpufreq_match_data match_data_msm8916 = {
> > > > +	/*
> > > > +	 * FIXME: Might need to implement .get_version here to handle
> > > > +	 * different frequencies depending on speedbin/pvs version.
> > > > +	 */
> > > > +	.genpd_names = msm8916_genpd_names,
> > > > +};
> > > > +
> > > >  static const char *qcs404_genpd_names[] = { "cpr", NULL };
> > > >  
> > > >  static const struct qcom_cpufreq_match_data match_data_qcs404 = {
> > > > @@ -301,6 +311,7 @@ static struct platform_driver qcom_cpufreq_driver = {
> > > >  
> > > >  static const struct of_device_id qcom_cpufreq_match_list[] __initconst = {
> > > >  	{ .compatible = "qcom,apq8096", .data = &match_data_kryo },
> > > > +	{ .compatible = "qcom,msm8916", .data = &match_data_msm8916 },
> > > >  	{ .compatible = "qcom,msm8996", .data = &match_data_kryo },
> > > >  	{ .compatible = "qcom,qcs404", .data = &match_data_qcs404 },
> > > >  	{},
> > > > diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c
> > > > index 2b1834c5609a..192ba9099964 100644
> > > > --- a/drivers/soc/qcom/rpmpd.c
> > > > +++ b/drivers/soc/qcom/rpmpd.c
> > > > @@ -115,6 +115,26 @@ struct rpmpd_desc {
> > > >  
> > > >  static DEFINE_MUTEX(rpmpd_lock);
> > > >  
> > > > +/* msm8916 RPM Power Domains */
> > > > +DEFINE_RPMPD_PAIR(msm8916, vddcx, vddcx_ao, SMPA, CORNER, 1);
> > > > +DEFINE_RPMPD_PAIR(msm8916, vddmx, vddmx_ao, LDOA, CORNER, 3);
> > > > +
> > > > +DEFINE_RPMPD_VFC(msm8916, vddcx_vfc, SMPA, 1);
> > > > +
> > > > +static struct rpmpd *msm8916_rpmpds[] = {
> > > > +	[MSM8916_VDDCX] =	&msm8916_vddcx,
> > > > +	[MSM8916_VDDCX_AO] =	&msm8916_vddcx_ao,
> > > > +	[MSM8916_VDDCX_VFC] =	&msm8916_vddcx_vfc,
> > > > +	[MSM8916_VDDMX] =	&msm8916_vddmx,
> > > > +	[MSM8916_VDDMX_AO] =	&msm8916_vddmx_ao,
> > > > +};
> > > > +
> > > > +static const struct rpmpd_desc msm8916_desc = {
> > > > +	.rpmpds = msm8916_rpmpds,
> > > > +	.num_pds = ARRAY_SIZE(msm8916_rpmpds),
> > > > +	.max_state = MAX_8996_RPMPD_STATE,
> > > > +};
> > > > +
> > > >  /* msm8976 RPM Power Domains */
> > > >  DEFINE_RPMPD_PAIR(msm8976, vddcx, vddcx_ao, SMPA, LEVEL, 2);
> > > >  DEFINE_RPMPD_PAIR(msm8976, vddmx, vddmx_ao, SMPA, LEVEL, 6);
> > > > @@ -220,6 +240,7 @@ static const struct rpmpd_desc qcs404_desc = {
> > > >  };
> > > >  
> > > >  static const struct of_device_id rpmpd_match_table[] = {
> > > > +	{ .compatible = "qcom,msm8916-rpmpd", .data = &msm8916_desc },
> > > >  	{ .compatible = "qcom,msm8976-rpmpd", .data = &msm8976_desc },
> > > >  	{ .compatible = "qcom,msm8996-rpmpd", .data = &msm8996_desc },
> > > >  	{ .compatible = "qcom,msm8998-rpmpd", .data = &msm8998_desc },
> > > > diff --git a/include/dt-bindings/power/qcom-rpmpd.h b/include/dt-bindings/power/qcom-rpmpd.h
> > > > index 3f74096d5a7c..70d304a2deae 100644
> > > > --- a/include/dt-bindings/power/qcom-rpmpd.h
> > > > +++ b/include/dt-bindings/power/qcom-rpmpd.h
> > > > @@ -51,6 +51,13 @@
> > > >  #define RPMH_REGULATOR_LEVEL_TURBO	384
> > > >  #define RPMH_REGULATOR_LEVEL_TURBO_L1	416
> > > >  
> > > > +/* MSM8916 Power Domain Indexes */
> > > > +#define MSM8916_VDDCX		0
> > > > +#define MSM8916_VDDCX_AO	1
> > > > +#define MSM8916_VDDCX_VFC	2
> > > > +#define MSM8916_VDDMX		3
> > > > +#define MSM8916_VDDMX_AO	4
> > > > +
> > > >  /* MSM8976 Power Domain Indexes */
> > > >  #define MSM8976_VDDCX		0
> > > >  #define MSM8976_VDDCX_AO	1

[-- Attachment #2: msm8916-vdd-mx.patch --]
[-- Type: text/plain, Size: 10913 bytes --]

diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
index 9254e4423d0c..b7e871d8f857 100644
--- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
@@ -11,6 +11,7 @@
 #include <dt-bindings/sound/qcom,q6afe.h>
 #include <dt-bindings/sound/qcom,q6asm.h>
 #include <dt-bindings/thermal/thermal.h>
+#include <dt-bindings/power/qcom-rpmpd.h>
 
 / {
 	interrupt-parent = <&intc>;
@@ -106,10 +107,11 @@ CPU0: cpu@0 {
 			next-level-cache = <&L2_0>;
 			enable-method = "psci";
 			clocks = <&apcs>;
+			cpu-supply = <&pm8916_spmi_s2>;
 			operating-points-v2 = <&cpu_opp_table>;
 			#cooling-cells = <2>;
-			power-domains = <&CPU_PD0>;
-			power-domain-names = "psci";
+			power-domains = <&CPU_PD0>, <&rpmpd MSM8916_VDDMX_AO>;
+			power-domain-names = "psci", "mx";
 		};
 
 		CPU1: cpu@1 {
@@ -119,10 +121,11 @@ CPU1: cpu@1 {
 			next-level-cache = <&L2_0>;
 			enable-method = "psci";
 			clocks = <&apcs>;
+			cpu-supply = <&pm8916_spmi_s2>;
 			operating-points-v2 = <&cpu_opp_table>;
 			#cooling-cells = <2>;
-			power-domains = <&CPU_PD1>;
-			power-domain-names = "psci";
+			power-domains = <&CPU_PD1>, <&rpmpd MSM8916_VDDMX_AO>;
+			power-domain-names = "psci", "mx";
 		};
 
 		CPU2: cpu@2 {
@@ -132,10 +135,11 @@ CPU2: cpu@2 {
 			next-level-cache = <&L2_0>;
 			enable-method = "psci";
 			clocks = <&apcs>;
+			cpu-supply = <&pm8916_spmi_s2>;
 			operating-points-v2 = <&cpu_opp_table>;
 			#cooling-cells = <2>;
-			power-domains = <&CPU_PD2>;
-			power-domain-names = "psci";
+			power-domains = <&CPU_PD2>, <&rpmpd MSM8916_VDDMX_AO>;
+			power-domain-names = "psci", "mx";
 		};
 
 		CPU3: cpu@3 {
@@ -145,10 +149,11 @@ CPU3: cpu@3 {
 			next-level-cache = <&L2_0>;
 			enable-method = "psci";
 			clocks = <&apcs>;
+			cpu-supply = <&pm8916_spmi_s2>;
 			operating-points-v2 = <&cpu_opp_table>;
 			#cooling-cells = <2>;
-			power-domains = <&CPU_PD3>;
-			power-domain-names = "psci";
+			power-domains = <&CPU_PD3>, <&rpmpd MSM8916_VDDMX_AO>;
+			power-domain-names = "psci", "mx";
 		};
 
 		L2_0: l2-cache {
@@ -340,20 +345,48 @@ modem_alert0: trip-point@0 {
 	};
 
 	cpu_opp_table: cpu_opp_table {
-		compatible = "operating-points-v2";
+		compatible = "operating-points-v2-qcom-cpu";
 		opp-shared;
 
 		opp-200000000 {
 			opp-hz = /bits/ 64 <200000000>;
+			opp-microvolt = <1050000>;
+			required-opps = <&rpmpd_opp_svs_soc>;
 		};
 		opp-400000000 {
 			opp-hz = /bits/ 64 <400000000>;
+			opp-microvolt = <1050000>;
+			required-opps = <&rpmpd_opp_svs_soc>;
+		};
+		opp-533330000 {
+			opp-hz = /bits/ 64 <533330000>;
+			opp-microvolt = <1150000>;
+			required-opps = <&rpmpd_opp_nom>;
 		};
 		opp-800000000 {
 			opp-hz = /bits/ 64 <800000000>;
+			opp-microvolt = <1150000>;
+			required-opps = <&rpmpd_opp_nom>;
 		};
 		opp-998400000 {
 			opp-hz = /bits/ 64 <998400000>;
+			opp-microvolt = <1350000>;
+			required-opps = <&rpmpd_opp_super_turbo>;
+		};
+		opp-1094400000 {
+			opp-hz = /bits/ 64 <1094400000>;
+			opp-microvolt = <1350000>;
+			required-opps = <&rpmpd_opp_super_turbo>;
+		};
+		opp-1152000000 {
+			opp-hz = /bits/ 64 <1152000000>;
+			opp-microvolt = <1350000>;
+			required-opps = <&rpmpd_opp_super_turbo>;
+		};
+		opp-1209600000 {
+			opp-hz = /bits/ 64 <1209600000>;
+			opp-microvolt = <1350000>;
+			required-opps = <&rpmpd_opp_super_turbo>;
 		};
 	};
 
@@ -1725,10 +1758,45 @@ rpmcc: qcom,rpmcc {
 					#clock-cells = <1>;
 				};
 
+				rpmpd: power-controller {
+					compatible = "qcom,msm8916-rpmpd";
+					#power-domain-cells = <1>;
+					operating-points-v2 = <&rpmpd_opp_table>;
+
+					rpmpd_opp_table: opp-table {
+						compatible = "operating-points-v2";
+
+						rpmpd_opp_ret: opp1 {
+							opp-level = <1>;
+						};
+
+						rpmpd_opp_svs: opp2 {
+							opp-level = <2>;
+						};
+
+						rpmpd_opp_svs_soc: opp3 {
+							opp-level = <3>;
+						};
+
+						rpmpd_opp_nom: opp4 {
+							opp-level = <4>;
+						};
+
+						rpmpd_opp_turbo: opp5 {
+							opp-level = <5>;
+						};
+
+						rpmpd_opp_super_turbo: opp6 {
+							opp-level = <6>;
+						};
+					};
+				};
+
 				smd_rpm_regulators: pm8916-regulators {
 					compatible = "qcom,rpm-pm8916-regulators";
 
 					pm8916_s1: s1 {};
+					/* s2 is directly controlled via spmi */
 					pm8916_s3: s3 {};
 					pm8916_s4: s4 {};
 
diff --git a/arch/arm64/boot/dts/qcom/pm8916.dtsi b/arch/arm64/boot/dts/qcom/pm8916.dtsi
index cbb96f23c2f7..c1505fc4a077 100644
--- a/arch/arm64/boot/dts/qcom/pm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8916.dtsi
@@ -163,5 +163,18 @@ wcd_codec: codec@f000 {
 			vdd-micbias-supply = <&pm8916_l13>;
 			#sound-dai-cells = <1>;
 		};
+
+		spmi_regulators: spmi_regulators  {
+			compatible = "qcom,pm8916-regulators";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			pm8916_spmi_s2: s2 {
+				regulator-always-on;
+				regulator-min-microvolt = <1050000>;
+				regulator-max-microvolt = <1350000>;
+			};
+			/* other regulators can be controlled via rpm */
+		};
 	};
 };
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
index cb9db16bea61..4a261101de3f 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -128,6 +128,7 @@ static const struct of_device_id blacklist[] __initconst = {
 	{ .compatible = "nvidia,tegra210", },
 
 	{ .compatible = "qcom,apq8096", },
+	{ .compatible = "qcom,msm8916", },
 	{ .compatible = "qcom,msm8996", },
 	{ .compatible = "qcom,qcs404", },
 
diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
index a1b8238872a2..16d31f724bb8 100644
--- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
+++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
@@ -26,6 +26,7 @@
 #include <linux/platform_device.h>
 #include <linux/pm_domain.h>
 #include <linux/pm_opp.h>
+#include <linux/pm_runtime.h>
 #include <linux/slab.h>
 #include <linux/soc/qcom/smem.h>
 
@@ -252,6 +253,16 @@ static const struct qcom_cpufreq_match_data match_data_krait = {
 	.get_version = qcom_cpufreq_krait_name_version,
 };
 
+static const char *msm8916_genpd_names[] = { "mx", NULL };
+
+static const struct qcom_cpufreq_match_data match_data_msm8916 = {
+	/*
+	 * FIXME: Might need to implement .get_version here to handle
+	 * different frequencies depending on speedbin/pvs version.
+	 */
+	.genpd_names = msm8916_genpd_names,
+};
+
 static const char *qcs404_genpd_names[] = { "cpr", NULL };
 
 static const struct qcom_cpufreq_match_data match_data_qcs404 = {
@@ -370,10 +381,13 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
 		}
 
 		if (drv->data->genpd_names) {
+			struct device **pd_dev;
+			const char **name = drv->data->genpd_names;
+
 			drv->genpd_opp_tables[cpu] =
 				dev_pm_opp_attach_genpd(cpu_dev,
 							drv->data->genpd_names,
-							NULL);
+							&pd_dev);
 			if (IS_ERR(drv->genpd_opp_tables[cpu])) {
 				ret = PTR_ERR(drv->genpd_opp_tables[cpu]);
 				if (ret != -EPROBE_DEFER)
@@ -382,6 +396,12 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
 						ret);
 				goto free_genpd_opp;
 			}
+
+			while (*name) {
+				pm_runtime_get_sync(*pd_dev);
+				name++;
+				pd_dev++;
+			}
 		}
 	}
 
@@ -456,6 +476,7 @@ static struct platform_driver qcom_cpufreq_driver = {
 
 static const struct of_device_id qcom_cpufreq_match_list[] __initconst = {
 	{ .compatible = "qcom,apq8096", .data = &match_data_kryo },
+	{ .compatible = "qcom,msm8916", .data = &match_data_msm8916 },
 	{ .compatible = "qcom,msm8996", .data = &match_data_kryo },
 	{ .compatible = "qcom,qcs404", .data = &match_data_qcs404 },
 	{ .compatible = "qcom,ipq8064", .data = &match_data_krait },
diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c
index 2b1834c5609a..705a52b9ebc5 100644
--- a/drivers/soc/qcom/rpmpd.c
+++ b/drivers/soc/qcom/rpmpd.c
@@ -115,6 +115,26 @@ struct rpmpd_desc {
 
 static DEFINE_MUTEX(rpmpd_lock);
 
+/* msm8916 RPM Power Domains */
+DEFINE_RPMPD_PAIR(msm8916, vddcx, vddcx_ao, SMPA, CORNER, 1);
+DEFINE_RPMPD_PAIR(msm8916, vddmx, vddmx_ao, LDOA, CORNER, 3);
+
+DEFINE_RPMPD_VFC(msm8916, vddcx_vfc, SMPA, 1);
+
+static struct rpmpd *msm8916_rpmpds[] = {
+	[MSM8916_VDDCX] =	&msm8916_vddcx,
+	[MSM8916_VDDCX_AO] =	&msm8916_vddcx_ao,
+	[MSM8916_VDDCX_VFC] =	&msm8916_vddcx_vfc,
+	[MSM8916_VDDMX] =	&msm8916_vddmx,
+	[MSM8916_VDDMX_AO] =	&msm8916_vddmx_ao,
+};
+
+static const struct rpmpd_desc msm8916_desc = {
+	.rpmpds = msm8916_rpmpds,
+	.num_pds = ARRAY_SIZE(msm8916_rpmpds),
+	.max_state = MAX_8996_RPMPD_STATE,
+};
+
 /* msm8976 RPM Power Domains */
 DEFINE_RPMPD_PAIR(msm8976, vddcx, vddcx_ao, SMPA, LEVEL, 2);
 DEFINE_RPMPD_PAIR(msm8976, vddmx, vddmx_ao, SMPA, LEVEL, 6);
@@ -220,6 +240,7 @@ static const struct rpmpd_desc qcs404_desc = {
 };
 
 static const struct of_device_id rpmpd_match_table[] = {
+	{ .compatible = "qcom,msm8916-rpmpd", .data = &msm8916_desc },
 	{ .compatible = "qcom,msm8976-rpmpd", .data = &msm8976_desc },
 	{ .compatible = "qcom,msm8996-rpmpd", .data = &msm8996_desc },
 	{ .compatible = "qcom,msm8998-rpmpd", .data = &msm8998_desc },
@@ -235,6 +256,8 @@ static int rpmpd_send_enable(struct rpmpd *pd, bool enable)
 		.value = cpu_to_le32(enable),
 	};
 
+	pr_err("rpmpd enable %#x %#x: %d\n", pd->res_type, pd->res_id, enable);
+
 	return qcom_rpm_smd_write(pd->rpm, QCOM_SMD_RPM_ACTIVE_STATE,
 				  pd->res_type, pd->res_id, &req, sizeof(req));
 }
@@ -247,6 +270,8 @@ static int rpmpd_send_corner(struct rpmpd *pd, int state, unsigned int corner)
 		.value = cpu_to_le32(corner),
 	};
 
+	pr_err("rpmpd corner %#x %#x state %d: %u\n", pd->res_type, pd->res_id, state, corner);
+
 	return qcom_rpm_smd_write(pd->rpm, state, pd->res_type, pd->res_id,
 				  &req, sizeof(req));
 };
@@ -331,6 +356,8 @@ static int rpmpd_set_performance(struct generic_pm_domain *domain,
 	int ret = 0;
 	struct rpmpd *pd = domain_to_rpmpd(domain);
 
+	pr_err("set performance: %d\n", state);
+
 	if (state > pd->max_state)
 		state = pd->max_state;
 
@@ -340,8 +367,10 @@ static int rpmpd_set_performance(struct generic_pm_domain *domain,
 
 	/* Always send updates for vfc and vfl */
 	if (!pd->enabled && pd->key != KEY_FLOOR_CORNER &&
-	    pd->key != KEY_FLOOR_LEVEL)
+	    pd->key != KEY_FLOOR_LEVEL) {
+		pr_err("not enabled\n");
 		goto out;
+	}
 
 	ret = rpmpd_aggregate_corner(pd);
 
diff --git a/include/dt-bindings/power/qcom-rpmpd.h b/include/dt-bindings/power/qcom-rpmpd.h
index 3f74096d5a7c..70d304a2deae 100644
--- a/include/dt-bindings/power/qcom-rpmpd.h
+++ b/include/dt-bindings/power/qcom-rpmpd.h
@@ -51,6 +51,13 @@
 #define RPMH_REGULATOR_LEVEL_TURBO	384
 #define RPMH_REGULATOR_LEVEL_TURBO_L1	416
 
+/* MSM8916 Power Domain Indexes */
+#define MSM8916_VDDCX		0
+#define MSM8916_VDDCX_AO	1
+#define MSM8916_VDDCX_VFC	2
+#define MSM8916_VDDMX		3
+#define MSM8916_VDDMX_AO	4
+
 /* MSM8976 Power Domain Indexes */
 #define MSM8976_VDDCX		0
 #define MSM8976_VDDCX_AO	1

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps
  2020-05-07  5:34               ` Bjorn Andersson
@ 2020-05-08 12:08                 ` Ulf Hansson
  2020-05-08 13:42                   ` Stephan Gerhold
  2020-05-11  5:29                   ` Viresh Kumar
  0 siblings, 2 replies; 32+ messages in thread
From: Ulf Hansson @ 2020-05-08 12:08 UTC (permalink / raw)
  To: Bjorn Andersson, Stephan Gerhold
  Cc: Viresh Kumar, Loic Poulain, Andy Gross, linux-arm-msm, Lina Iyer

+ Lina

On Thu, 7 May 2020 at 07:33, Bjorn Andersson <bjorn.andersson@linaro.org> wrote:
>
> On Wed 06 May 14:18 PDT 2020, Stephan Gerhold wrote:
>
> Viresh, Ulf,
>
> Stephan is trying to describe the relationship between the CPU rail and
> the memory rail on db410c (where the performance state of the memory
> rail needs to be kept above the performance state of the CPU supply.
>
> The latter is modelled as a power-domain and the performance state
> changes as expected, but no one enables the power-domain.

Just to make one thing clear, from a genpd framework point of view,
power on/off of a genpd is orthogonal to setting/aggregating
performance states for it.

It's instead up to the genpd provider to deal with this (as I
understand, that seems to be the issue from the below discussions).

>
> What's the appropriate method for ensuring the power-domain is
> enabled/disabled as needed? Should it be referenced in the hierarchical
> power domain for the CPUs perhaps?

If I understand the dependency correctly, perhaps you are right that
there needs to be a subdomain assigned. Although, I don't know if this
ever has been tested to work for a real use case, when it comes to
performance state propagations upwards in the hierarchy.

Viresh?

If you also need to manage genpd power on/off, that should be managed
by using runtime PM reference counting on those devices that are
attached to the genpd in question.

Kind regards
Uffe


>
> Regards,
> Bjorn
>
> > Hi,
> >
> > On Sun, Apr 26, 2020 at 02:31:48PM +0200, Stephan Gerhold wrote:
> > > On Wed, Apr 22, 2020 at 09:55:06PM -0700, Bjorn Andersson wrote:
> > > > On Fri 03 Apr 11:00 PDT 2020, Stephan Gerhold wrote:
> > > >
> > > > > On Fri, Apr 03, 2020 at 12:09:25PM +0200, Stephan Gerhold wrote:
> > > > > > On Thu, Apr 02, 2020 at 06:31:19PM -0700, Bjorn Andersson wrote:
> > > > > > > On Thu 02 Apr 01:13 PDT 2020, Stephan Gerhold wrote:
> > > > > > >
> > > > > > > > Hi,
> > > > > > > >
> > > > > > > > On Wed, Apr 01, 2020 at 07:50:59PM +0200, Loic Poulain wrote:
> > > > > > > > > The highest cpu frequency opps have been dropped because CPR is not
> > > > > > > > > supported. However, we can simply specify operating voltage so that
> > > > > > > > > they match the max corner voltages for each freq. With that, we can
> > > > > > > > > support up to 1.36Ghz. Ideally, msm8916 CPR should be implemented to
> > > > > > > > > fine tune operating voltages and optimize power consumption.
> > > > > > > >
> > > > > > > > Thanks for the patch! I was wondering how to enable the higher CPU
> > > > > > > > frequencies for a while now...
> > > > > > > >
> > > > > > > > I was actually quite excited to see CPR being mainlined for QCS404.
> > > > > > > > If we are trying to add such a workaround (rather than CPR) for MSM8916
> > > > > > > > now, does that mean it's unlikely to see CPR working for MSM8916
> > > > > > > > anytime soon?
> > > > > > > >
> > > > > > > > AFAICT, there is a WIP branch from Niklas Cassel here:
> > > > > > > > https://git.linaro.org/people/nicolas.dechesne/niklas.cassel/kernel.git/log/?h=cpr-msm8916-mainline
> > > > > > > > but it hasn't been updated for a while. (Not sure if it was working
> > > > > > > > already...)
> > > > > > > >
> > > > > > > > Can someone explain what is missing to make CPR work for MSM8916?
> > > > > > > >
> > > > > > >
> > > > > > > CPR needs to control 3 things; VDD_APC, VDD_MX and MEMACC. On QCS404 it
> > > > > > > seems we don't have to adjust VDD_MX, so the code for this is missing
> > > > > > > from the driver.
> > > > > > >
> > > > > > > So, afaict, what's missing is that rpmpd.c needs to gain support for
> > > > > > > 8916, then the CPR driver needs to gain a cpr_acc_desc and compatible
> > > > > > > for 8916, it needs to reference the VDDMX power domain and before/after
> > > > > > > we're adjusting the corner of the CPR we need to adjust the MX according
> > > > > > > to the mapping specified in the downstream kernel (i.e.  1->4, 2->5 and
> > > > > > > 3->7).
> > > > > > >
> > > > > > >
> > > > > > > Unfortunately, the requirement that VDDMX (VDD_MEM I presume) must be
> > > > > > > higher than VDD_APC most likely needs to be taken into consideration for
> > > > > > > Loic's proposed static voltage scaling as well. Unless VDD_MEM is left
> > > > > > > in Turbo mode from the boot loader I think we need to take VDDMX to
> > > > > > > corner 7 for speeds 998MHz and above (i.e. where we pull VDD_APC to
> > > > > > > 1.35V).
> > > > > > >
> > > > > >
> > > > > > I see! I wonder how hard it would be to add MSM8916 to rpmpd,
> > > > > > looking at previous commits it's mainly setting up a few defines?
> > > > > >
> > > > > > If I understand it correctly, the OPPs from rpmpd could then be
> > > > > > referenced as "required-opps" in the CPU OPP table so that VDD_MX is
> > > > > > scaled together with the CPU frequency, and doesn't need to stay at
> > > > > > turbo mode (like in v3 from Loic) the whole time.
> > > > > >
> > > > >
> > > > > I have been thinking about this some more and I think I came up with
> > > > > some changes that make sense (but not entirely sure).
> > > > >
> > > > > Based on the available downstream sources I guessed the defines to add
> > > > > for MSM8916 to the rpmpd driver. Then I added the VDD_MX OPPs as
> > > > > "required-opps" to the CPU OPP table so it would vote for the appopriate
> > > > > corners (with the mapping you mentioned above).
> > > > >
> > > >
> > > > I was not aware it was possible to describe the dependency between the
> > > > CPU opp table and MX in this fashion. If that's the case then this looks
> > > > really good and it should be straight forward to add MSM8916 support to
> > > > the CPR driver as well.
> > > >
> > >
> > > Indeed!
> > >
> > > > > I haven't tested it yet, maybe I can get some feedback first if the code
> > > > > seems reasonable or if I'm missing something obvious? :)
> > > > >
> > > >
> > > > Have you tested this yet?
> > > >
> > >
> > > I just did. It does not fully work, yet:
> > >
> > > rpmpd_set_performance() is indeed called as necessary when switching the
> > > CPU frequency. When I set 200 MHz it sets corner 3, with 533 MHz corner 4
> > > and starting with 998 MHz corner 6. So far so good :)
> > >
> > > However, there is never actually anything sent to the RPM. :(
> > > It bails out in rpmpd_set_performance() before calling rpmpd_aggregate_corner():
> > >
> > >     /* Always send updates for vfc and vfl */
> > >     if (!pd->enabled && pd->key != KEY_FLOOR_CORNER &&
> > >         pd->key != KEY_FLOOR_LEVEL)
> > >             goto out;
> > >
> > > Seems like we just try to set performance states, but never actually
> > > enable (rpmpd_power_on()) the power domain (pd->enabled == false).
> > >
> > > I'm not sure which of the components involved here should handle that.
> > > The OPP core when setting required OPPs, the genpd core etc.
> > >
> > > Any ideas?
> > >
> > > Thanks,
> > > Stephan
> > >
> >
> > For now I have added something to qcom-cpufreq-nvmem.c to power on/enable
> > the power domain (not really sure if it belongs there...):
> >
> > diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > index a1b8238872a2..ed352ead037e 100644
> > --- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > +++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > @@ -26,6 +26,7 @@
> >  #include <linux/platform_device.h>
> >  #include <linux/pm_domain.h>
> >  #include <linux/pm_opp.h>
> > +#include <linux/pm_runtime.h>
> >  #include <linux/slab.h>
> >  #include <linux/soc/qcom/smem.h>
> >
> > @@ -370,10 +371,13 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
> >               }
> >
> >               if (drv->data->genpd_names) {
> > +                     struct device **pd_dev;
> > +                     const char **name = drv->data->genpd_names;
> > +
> >                       drv->genpd_opp_tables[cpu] =
> >                               dev_pm_opp_attach_genpd(cpu_dev,
> >                                                       drv->data->genpd_names,
> > -                                                     NULL);
> > +                                                     &pd_dev);
> >                       if (IS_ERR(drv->genpd_opp_tables[cpu])) {
> >                               ret = PTR_ERR(drv->genpd_opp_tables[cpu]);
> >                               if (ret != -EPROBE_DEFER)
> > @@ -382,6 +386,12 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
> >                                               ret);
> >                               goto free_genpd_opp;
> >                       }
> > +
> > +                     while (*name) {
> > +                             pm_runtime_get_sync(*pd_dev);
> > +                             name++;
> > +                             pd_dev++;
> > +                     }
> >               }
> >       }
> >
> > I really wonder why this doesn't affect CPR (or does it?).
> > So far I was not able to find anything that would power on/enable
> > the "cpr" power domain either. But I don't have a qcs404 to verify.
> >
> > As far as I can tell from the log, the corner votes are correctly sent
> > to the RPM now when the CPU frequency is changed.
> >
> > However...
> >
> > > > > Also: Is there a good way to validate these changes?
> > > > > I suppose I could check the genpd state but that wouldn't tell me if the
> > > > > corner was applied correctly. Maybe I can check the actual voltage
> > > > > through the SPMI interface, hm...
> > > > >
> > > >
> > > > Validating that S2 and VDD_MX changes appropriately in Linux would be a
> > > > pretty good test.
> > > >
> >
> > Unfortunately I was not able to see any change in the voltage of L3 yet.
> > On samsung-a5u, /sys/class/regulator/<l3 spmi regulator>/microvolts
> > permanently reports 1300000 uV, even after a few different corner votes.
> >
> > I'm not sure if:
> >
> >   - This is normal (maybe some other remoteproc has a higher vote?)
> >     - I tried to disable wcnss, venus and hexagon without difference
> >
> >   - I'm just missing something in the code
> >
> >   - This is some peculiarity of the RPM firmware on samsung-a5u.
> >     (Although that seems quite unlikely to me...)
> >
> > Any ideas? :/
> >
> > Thanks,
> > Stephan
> >
> > > > > If this seems like a good approach I can split up the changes in
> > > > > reasonable patches and post it separately. For now the full diff below.
> > > > >
> > > >
> > > > Please do
> > > >
> > > > Regards,
> > > > Bjorn
> > > >
> > > > > Stephan
> > > > >
> > > > >  arch/arm64/boot/dts/qcom/msm8916.dtsi  | 65 +++++++++++++++++++++++++++++-----
> > > > >  drivers/cpufreq/cpufreq-dt-platdev.c   |  1 +
> > > > >  drivers/cpufreq/qcom-cpufreq-nvmem.c   | 11 ++++++
> > > > >  drivers/soc/qcom/rpmpd.c               | 21 +++++++++++
> > > > >  include/dt-bindings/power/qcom-rpmpd.h |  7 ++++
> > > > >  5 files changed, 96 insertions(+), 9 deletions(-)
> > > > >
> > > > > diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > > > > index b0a82447976a..5b8fce8609d0 100644
> > > > > --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > > > > +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > > > > @@ -10,6 +10,7 @@
> > > > >  #include <dt-bindings/soc/qcom,apr.h>
> > > > >  #include <dt-bindings/sound/qcom,q6afe.h>
> > > > >  #include <dt-bindings/thermal/thermal.h>
> > > > > +#include <dt-bindings/power/qcom-rpmpd.h>
> > > > >
> > > > >  / {
> > > > >         interrupt-parent = <&intc>;
> > > > > @@ -108,8 +109,8 @@ CPU0: cpu@0 {
> > > > >                         cpu-supply = <&pm8916_spmi_s2>;
> > > > >                         operating-points-v2 = <&cpu_opp_table>;
> > > > >                         #cooling-cells = <2>;
> > > > > -                       power-domains = <&CPU_PD0>;
> > > > > -                       power-domain-names = "psci";
> > > > > +                       power-domains = <&CPU_PD0>, <&rpmpd MSM8916_VDDMX_AO>;
> > > > > +                       power-domain-names = "psci", "mx";
> > > > >                 };
> > > > >
> > > > >                 CPU1: cpu@1 {
> > > > > @@ -122,8 +123,8 @@ CPU1: cpu@1 {
> > > > >                         cpu-supply = <&pm8916_spmi_s2>;
> > > > >                         operating-points-v2 = <&cpu_opp_table>;
> > > > >                         #cooling-cells = <2>;
> > > > > -                       power-domains = <&CPU_PD1>;
> > > > > -                       power-domain-names = "psci";
> > > > > +                       power-domains = <&CPU_PD1>, <&rpmpd MSM8916_VDDMX_AO>;
> > > > > +                       power-domain-names = "psci", "mx";
> > > > >                 };
> > > > >
> > > > >                 CPU2: cpu@2 {
> > > > > @@ -136,8 +137,8 @@ CPU2: cpu@2 {
> > > > >                         cpu-supply = <&pm8916_spmi_s2>;
> > > > >                         operating-points-v2 = <&cpu_opp_table>;
> > > > >                         #cooling-cells = <2>;
> > > > > -                       power-domains = <&CPU_PD2>;
> > > > > -                       power-domain-names = "psci";
> > > > > +                       power-domains = <&CPU_PD2>, <&rpmpd MSM8916_VDDMX_AO>;
> > > > > +                       power-domain-names = "psci", "mx";
> > > > >                 };
> > > > >
> > > > >                 CPU3: cpu@3 {
> > > > > @@ -150,8 +151,8 @@ CPU3: cpu@3 {
> > > > >                         cpu-supply = <&pm8916_spmi_s2>;
> > > > >                         operating-points-v2 = <&cpu_opp_table>;
> > > > >                         #cooling-cells = <2>;
> > > > > -                       power-domains = <&CPU_PD3>;
> > > > > -                       power-domain-names = "psci";
> > > > > +                       power-domains = <&CPU_PD3>, <&rpmpd MSM8916_VDDMX_AO>;
> > > > > +                       power-domain-names = "psci", "mx";
> > > > >                 };
> > > > >
> > > > >                 L2_0: l2-cache {
> > > > > @@ -343,40 +344,52 @@ modem_alert0: trip-point@0 {
> > > > >         };
> > > > >
> > > > >         cpu_opp_table: cpu_opp_table {
> > > > > -               compatible = "operating-points-v2";
> > > > > +               /*
> > > > > +                * FIXME: The naming here is really weird, since MSM8916 does
> > > > > +                * not have kyro. Maybe we should add a more generic compatible?
> > > > > +                */
> > > > > +               compatible = "operating-points-v2-kryo-cpu";
> > > > >                 opp-shared;
> > > > >
> > > > >                 opp-200000000 {
> > > > >                         opp-hz = /bits/ 64 <200000000>;
> > > > >                         opp-microvolt = <1050000>;
> > > > > +                       required-opps = <&rpmpd_opp_svs_soc>;
> > > > >                 };
> > > > >                 opp-400000000 {
> > > > >                         opp-hz = /bits/ 64 <400000000>;
> > > > >                         opp-microvolt = <1050000>;
> > > > > +                       required-opps = <&rpmpd_opp_svs_soc>;
> > > > >                 };
> > > > >                 opp-533330000 {
> > > > >                         opp-hz = /bits/ 64 <533330000>;
> > > > >                         opp-microvolt = <1150000>;
> > > > > +                       required-opps = <&rpmpd_opp_nom>;
> > > > >                 };
> > > > >                 opp-800000000 {
> > > > >                         opp-hz = /bits/ 64 <800000000>;
> > > > >                         opp-microvolt = <1150000>;
> > > > > +                       required-opps = <&rpmpd_opp_nom>;
> > > > >                 };
> > > > >                 opp-998400000 {
> > > > >                         opp-hz = /bits/ 64 <998400000>;
> > > > >                         opp-microvolt = <1350000>;
> > > > > +                       required-opps = <&rpmpd_opp_super_turbo>;
> > > > >                 };
> > > > >                 opp-1094400000 {
> > > > >                         opp-hz = /bits/ 64 <1094400000>;
> > > > >                         opp-microvolt = <1350000>;
> > > > > +                       required-opps = <&rpmpd_opp_super_turbo>;
> > > > >                 };
> > > > >                 opp-1152000000 {
> > > > >                         opp-hz = /bits/ 64 <1152000000>;
> > > > >                         opp-microvolt = <1350000>;
> > > > > +                       required-opps = <&rpmpd_opp_super_turbo>;
> > > > >                 };
> > > > >                 opp-1209600000 {
> > > > >                         opp-hz = /bits/ 64 <1209600000>;
> > > > >                         opp-microvolt = <1350000>;
> > > > > +                       required-opps = <&rpmpd_opp_super_turbo>;
> > > > >                 };
> > > > >         };
> > > > >
> > > > > @@ -1710,6 +1723,40 @@ rpmcc: qcom,rpmcc {
> > > > >                                         #clock-cells = <1>;
> > > > >                                 };
> > > > >
> > > > > +                               rpmpd: power-controller {
> > > > > +                                       compatible = "qcom,msm8916-rpmpd";
> > > > > +                                       #power-domain-cells = <1>;
> > > > > +                                       operating-points-v2 = <&rpmpd_opp_table>;
> > > > > +
> > > > > +                                       rpmpd_opp_table: opp-table {
> > > > > +                                               compatible = "operating-points-v2";
> > > > > +
> > > > > +                                               rpmpd_opp_ret: opp1 {
> > > > > +                                                       opp-level = <1>;
> > > > > +                                               };
> > > > > +
> > > > > +                                               rpmpd_opp_svs: opp2 {
> > > > > +                                                       opp-level = <2>;
> > > > > +                                               };
> > > > > +
> > > > > +                                               rpmpd_opp_svs_soc: opp3 {
> > > > > +                                                       opp-level = <3>;
> > > > > +                                               };
> > > > > +
> > > > > +                                               rpmpd_opp_nom: opp4 {
> > > > > +                                                       opp-level = <4>;
> > > > > +                                               };
> > > > > +
> > > > > +                                               rpmpd_opp_turbo: opp5 {
> > > > > +                                                       opp-level = <5>;
> > > > > +                                               };
> > > > > +
> > > > > +                                               rpmpd_opp_super_turbo: opp6 {
> > > > > +                                                       opp-level = <6>;
> > > > > +                                               };
> > > > > +                                       };
> > > > > +                               };
> > > > > +
> > > > >                                 smd_rpm_regulators: pm8916-regulators {
> > > > >                                         compatible = "qcom,rpm-pm8916-regulators";
> > > > >
> > > > > diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
> > > > > index f2ae9cd455c1..b0f6bd0fffc1 100644
> > > > > --- a/drivers/cpufreq/cpufreq-dt-platdev.c
> > > > > +++ b/drivers/cpufreq/cpufreq-dt-platdev.c
> > > > > @@ -128,6 +128,7 @@ static const struct of_device_id blacklist[] __initconst = {
> > > > >         { .compatible = "nvidia,tegra210", },
> > > > >
> > > > >         { .compatible = "qcom,apq8096", },
> > > > > +       { .compatible = "qcom,msm8916", },
> > > > >         { .compatible = "qcom,msm8996", },
> > > > >         { .compatible = "qcom,qcs404", },
> > > > >
> > > > > diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > > > > index f0d2d5035413..c77a30349d08 100644
> > > > > --- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > > > > +++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > > > > @@ -129,6 +129,16 @@ static const struct qcom_cpufreq_match_data match_data_kryo = {
> > > > >         .get_version = qcom_cpufreq_kryo_name_version,
> > > > >  };
> > > > >
> > > > > +static const char *msm8916_genpd_names[] = { "mx", NULL };
> > > > > +
> > > > > +static const struct qcom_cpufreq_match_data match_data_msm8916 = {
> > > > > +       /*
> > > > > +        * FIXME: Might need to implement .get_version here to handle
> > > > > +        * different frequencies depending on speedbin/pvs version.
> > > > > +        */
> > > > > +       .genpd_names = msm8916_genpd_names,
> > > > > +};
> > > > > +
> > > > >  static const char *qcs404_genpd_names[] = { "cpr", NULL };
> > > > >
> > > > >  static const struct qcom_cpufreq_match_data match_data_qcs404 = {
> > > > > @@ -301,6 +311,7 @@ static struct platform_driver qcom_cpufreq_driver = {
> > > > >
> > > > >  static const struct of_device_id qcom_cpufreq_match_list[] __initconst = {
> > > > >         { .compatible = "qcom,apq8096", .data = &match_data_kryo },
> > > > > +       { .compatible = "qcom,msm8916", .data = &match_data_msm8916 },
> > > > >         { .compatible = "qcom,msm8996", .data = &match_data_kryo },
> > > > >         { .compatible = "qcom,qcs404", .data = &match_data_qcs404 },
> > > > >         {},
> > > > > diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c
> > > > > index 2b1834c5609a..192ba9099964 100644
> > > > > --- a/drivers/soc/qcom/rpmpd.c
> > > > > +++ b/drivers/soc/qcom/rpmpd.c
> > > > > @@ -115,6 +115,26 @@ struct rpmpd_desc {
> > > > >
> > > > >  static DEFINE_MUTEX(rpmpd_lock);
> > > > >
> > > > > +/* msm8916 RPM Power Domains */
> > > > > +DEFINE_RPMPD_PAIR(msm8916, vddcx, vddcx_ao, SMPA, CORNER, 1);
> > > > > +DEFINE_RPMPD_PAIR(msm8916, vddmx, vddmx_ao, LDOA, CORNER, 3);
> > > > > +
> > > > > +DEFINE_RPMPD_VFC(msm8916, vddcx_vfc, SMPA, 1);
> > > > > +
> > > > > +static struct rpmpd *msm8916_rpmpds[] = {
> > > > > +       [MSM8916_VDDCX] =       &msm8916_vddcx,
> > > > > +       [MSM8916_VDDCX_AO] =    &msm8916_vddcx_ao,
> > > > > +       [MSM8916_VDDCX_VFC] =   &msm8916_vddcx_vfc,
> > > > > +       [MSM8916_VDDMX] =       &msm8916_vddmx,
> > > > > +       [MSM8916_VDDMX_AO] =    &msm8916_vddmx_ao,
> > > > > +};
> > > > > +
> > > > > +static const struct rpmpd_desc msm8916_desc = {
> > > > > +       .rpmpds = msm8916_rpmpds,
> > > > > +       .num_pds = ARRAY_SIZE(msm8916_rpmpds),
> > > > > +       .max_state = MAX_8996_RPMPD_STATE,
> > > > > +};
> > > > > +
> > > > >  /* msm8976 RPM Power Domains */
> > > > >  DEFINE_RPMPD_PAIR(msm8976, vddcx, vddcx_ao, SMPA, LEVEL, 2);
> > > > >  DEFINE_RPMPD_PAIR(msm8976, vddmx, vddmx_ao, SMPA, LEVEL, 6);
> > > > > @@ -220,6 +240,7 @@ static const struct rpmpd_desc qcs404_desc = {
> > > > >  };
> > > > >
> > > > >  static const struct of_device_id rpmpd_match_table[] = {
> > > > > +       { .compatible = "qcom,msm8916-rpmpd", .data = &msm8916_desc },
> > > > >         { .compatible = "qcom,msm8976-rpmpd", .data = &msm8976_desc },
> > > > >         { .compatible = "qcom,msm8996-rpmpd", .data = &msm8996_desc },
> > > > >         { .compatible = "qcom,msm8998-rpmpd", .data = &msm8998_desc },
> > > > > diff --git a/include/dt-bindings/power/qcom-rpmpd.h b/include/dt-bindings/power/qcom-rpmpd.h
> > > > > index 3f74096d5a7c..70d304a2deae 100644
> > > > > --- a/include/dt-bindings/power/qcom-rpmpd.h
> > > > > +++ b/include/dt-bindings/power/qcom-rpmpd.h
> > > > > @@ -51,6 +51,13 @@
> > > > >  #define RPMH_REGULATOR_LEVEL_TURBO     384
> > > > >  #define RPMH_REGULATOR_LEVEL_TURBO_L1  416
> > > > >
> > > > > +/* MSM8916 Power Domain Indexes */
> > > > > +#define MSM8916_VDDCX          0
> > > > > +#define MSM8916_VDDCX_AO       1
> > > > > +#define MSM8916_VDDCX_VFC      2
> > > > > +#define MSM8916_VDDMX          3
> > > > > +#define MSM8916_VDDMX_AO       4
> > > > > +
> > > > >  /* MSM8976 Power Domain Indexes */
> > > > >  #define MSM8976_VDDCX          0
> > > > >  #define MSM8976_VDDCX_AO       1

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps
  2020-05-08 12:08                 ` Ulf Hansson
@ 2020-05-08 13:42                   ` Stephan Gerhold
  2020-05-11  5:29                   ` Viresh Kumar
  1 sibling, 0 replies; 32+ messages in thread
From: Stephan Gerhold @ 2020-05-08 13:42 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Bjorn Andersson, Viresh Kumar, Loic Poulain, Andy Gross,
	linux-arm-msm, Lina Iyer

On Fri, May 08, 2020 at 02:08:09PM +0200, Ulf Hansson wrote:
> + Lina
> 
> On Thu, 7 May 2020 at 07:33, Bjorn Andersson <bjorn.andersson@linaro.org> wrote:
> >
> > On Wed 06 May 14:18 PDT 2020, Stephan Gerhold wrote:
> >
> > Viresh, Ulf,
> >
> > Stephan is trying to describe the relationship between the CPU rail and
> > the memory rail on db410c (where the performance state of the memory
> > rail needs to be kept above the performance state of the CPU supply.
> >
> > The latter is modelled as a power-domain and the performance state
> > changes as expected, but no one enables the power-domain.
> 
> Just to make one thing clear, from a genpd framework point of view,
> power on/off of a genpd is orthogonal to setting/aggregating
> performance states for it.
> 
> It's instead up to the genpd provider to deal with this (as I
> understand, that seems to be the issue from the below discussions).
> 
> >
> > What's the appropriate method for ensuring the power-domain is
> > enabled/disabled as needed? Should it be referenced in the hierarchical
> > power domain for the CPUs perhaps?
> 
> If I understand the dependency correctly, perhaps you are right that
> there needs to be a subdomain assigned. Although, I don't know if this
> ever has been tested to work for a real use case, when it comes to
> performance state propagations upwards in the hierarchy.
> 

What I don't understand is why this is only happening for me,
and not also for CPR on QCS404 (or does that have the same problem?).
See commit 04aadcaadd39 ("arm64: dts: qcom: qcs404: Add CPR and populate OPP table").

Essentially that works exactly like the "mx" power domain I'm trying to add,
it references the "cpr" power domain performance states from the CPU opps.
Someone also needs to power on the CPR power domain, and AFAICT there is
nothing that does that at the moment.

> Viresh?
> 
> If you also need to manage genpd power on/off, that should be managed
> by using runtime PM reference counting on those devices that are
> attached to the genpd in question.
> 

For testing I have added a pm_runtime_get_sync() for the virtual devices
returned by dev_pm_opp_attach_genpd() in qcom-cpufreq-nvmem.c.

That works fine, but it means the power domain is powered on
permanently. (Which might be the correct behavior in this case,
not sure powering off VDD_MX would ever work correctly...)

> Kind regards
> Uffe
> 
> 
> >
> > Regards,
> > Bjorn
> >
> > > Hi,
> > >
> > > On Sun, Apr 26, 2020 at 02:31:48PM +0200, Stephan Gerhold wrote:
> > > > On Wed, Apr 22, 2020 at 09:55:06PM -0700, Bjorn Andersson wrote:
> > > > > On Fri 03 Apr 11:00 PDT 2020, Stephan Gerhold wrote:
> > > > >
> > > > > > On Fri, Apr 03, 2020 at 12:09:25PM +0200, Stephan Gerhold wrote:
> > > > > > > On Thu, Apr 02, 2020 at 06:31:19PM -0700, Bjorn Andersson wrote:
> > > > > > > > On Thu 02 Apr 01:13 PDT 2020, Stephan Gerhold wrote:
> > > > > > > >
> > > > > > > > > Hi,
> > > > > > > > >
> > > > > > > > > On Wed, Apr 01, 2020 at 07:50:59PM +0200, Loic Poulain wrote:
> > > > > > > > > > The highest cpu frequency opps have been dropped because CPR is not
> > > > > > > > > > supported. However, we can simply specify operating voltage so that
> > > > > > > > > > they match the max corner voltages for each freq. With that, we can
> > > > > > > > > > support up to 1.36Ghz. Ideally, msm8916 CPR should be implemented to
> > > > > > > > > > fine tune operating voltages and optimize power consumption.
> > > > > > > > >
> > > > > > > > > Thanks for the patch! I was wondering how to enable the higher CPU
> > > > > > > > > frequencies for a while now...
> > > > > > > > >
> > > > > > > > > I was actually quite excited to see CPR being mainlined for QCS404.
> > > > > > > > > If we are trying to add such a workaround (rather than CPR) for MSM8916
> > > > > > > > > now, does that mean it's unlikely to see CPR working for MSM8916
> > > > > > > > > anytime soon?
> > > > > > > > >
> > > > > > > > > AFAICT, there is a WIP branch from Niklas Cassel here:
> > > > > > > > > https://git.linaro.org/people/nicolas.dechesne/niklas.cassel/kernel.git/log/?h=cpr-msm8916-mainline
> > > > > > > > > but it hasn't been updated for a while. (Not sure if it was working
> > > > > > > > > already...)
> > > > > > > > >
> > > > > > > > > Can someone explain what is missing to make CPR work for MSM8916?
> > > > > > > > >
> > > > > > > >
> > > > > > > > CPR needs to control 3 things; VDD_APC, VDD_MX and MEMACC. On QCS404 it
> > > > > > > > seems we don't have to adjust VDD_MX, so the code for this is missing
> > > > > > > > from the driver.
> > > > > > > >
> > > > > > > > So, afaict, what's missing is that rpmpd.c needs to gain support for
> > > > > > > > 8916, then the CPR driver needs to gain a cpr_acc_desc and compatible
> > > > > > > > for 8916, it needs to reference the VDDMX power domain and before/after
> > > > > > > > we're adjusting the corner of the CPR we need to adjust the MX according
> > > > > > > > to the mapping specified in the downstream kernel (i.e.  1->4, 2->5 and
> > > > > > > > 3->7).
> > > > > > > >
> > > > > > > >
> > > > > > > > Unfortunately, the requirement that VDDMX (VDD_MEM I presume) must be
> > > > > > > > higher than VDD_APC most likely needs to be taken into consideration for
> > > > > > > > Loic's proposed static voltage scaling as well. Unless VDD_MEM is left
> > > > > > > > in Turbo mode from the boot loader I think we need to take VDDMX to
> > > > > > > > corner 7 for speeds 998MHz and above (i.e. where we pull VDD_APC to
> > > > > > > > 1.35V).
> > > > > > > >
> > > > > > >
> > > > > > > I see! I wonder how hard it would be to add MSM8916 to rpmpd,
> > > > > > > looking at previous commits it's mainly setting up a few defines?
> > > > > > >
> > > > > > > If I understand it correctly, the OPPs from rpmpd could then be
> > > > > > > referenced as "required-opps" in the CPU OPP table so that VDD_MX is
> > > > > > > scaled together with the CPU frequency, and doesn't need to stay at
> > > > > > > turbo mode (like in v3 from Loic) the whole time.
> > > > > > >
> > > > > >
> > > > > > I have been thinking about this some more and I think I came up with
> > > > > > some changes that make sense (but not entirely sure).
> > > > > >
> > > > > > Based on the available downstream sources I guessed the defines to add
> > > > > > for MSM8916 to the rpmpd driver. Then I added the VDD_MX OPPs as
> > > > > > "required-opps" to the CPU OPP table so it would vote for the appopriate
> > > > > > corners (with the mapping you mentioned above).
> > > > > >
> > > > >
> > > > > I was not aware it was possible to describe the dependency between the
> > > > > CPU opp table and MX in this fashion. If that's the case then this looks
> > > > > really good and it should be straight forward to add MSM8916 support to
> > > > > the CPR driver as well.
> > > > >
> > > >
> > > > Indeed!
> > > >
> > > > > > I haven't tested it yet, maybe I can get some feedback first if the code
> > > > > > seems reasonable or if I'm missing something obvious? :)
> > > > > >
> > > > >
> > > > > Have you tested this yet?
> > > > >
> > > >
> > > > I just did. It does not fully work, yet:
> > > >
> > > > rpmpd_set_performance() is indeed called as necessary when switching the
> > > > CPU frequency. When I set 200 MHz it sets corner 3, with 533 MHz corner 4
> > > > and starting with 998 MHz corner 6. So far so good :)
> > > >
> > > > However, there is never actually anything sent to the RPM. :(
> > > > It bails out in rpmpd_set_performance() before calling rpmpd_aggregate_corner():
> > > >
> > > >     /* Always send updates for vfc and vfl */
> > > >     if (!pd->enabled && pd->key != KEY_FLOOR_CORNER &&
> > > >         pd->key != KEY_FLOOR_LEVEL)
> > > >             goto out;
> > > >
> > > > Seems like we just try to set performance states, but never actually
> > > > enable (rpmpd_power_on()) the power domain (pd->enabled == false).
> > > >
> > > > I'm not sure which of the components involved here should handle that.
> > > > The OPP core when setting required OPPs, the genpd core etc.
> > > >
> > > > Any ideas?
> > > >
> > > > Thanks,
> > > > Stephan
> > > >
> > >
> > > For now I have added something to qcom-cpufreq-nvmem.c to power on/enable
> > > the power domain (not really sure if it belongs there...):
> > >
> > > diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > > index a1b8238872a2..ed352ead037e 100644
> > > --- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > > +++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > > @@ -26,6 +26,7 @@
> > >  #include <linux/platform_device.h>
> > >  #include <linux/pm_domain.h>
> > >  #include <linux/pm_opp.h>
> > > +#include <linux/pm_runtime.h>
> > >  #include <linux/slab.h>
> > >  #include <linux/soc/qcom/smem.h>
> > >
> > > @@ -370,10 +371,13 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
> > >               }
> > >
> > >               if (drv->data->genpd_names) {
> > > +                     struct device **pd_dev;
> > > +                     const char **name = drv->data->genpd_names;
> > > +
> > >                       drv->genpd_opp_tables[cpu] =
> > >                               dev_pm_opp_attach_genpd(cpu_dev,
> > >                                                       drv->data->genpd_names,
> > > -                                                     NULL);
> > > +                                                     &pd_dev);
> > >                       if (IS_ERR(drv->genpd_opp_tables[cpu])) {
> > >                               ret = PTR_ERR(drv->genpd_opp_tables[cpu]);
> > >                               if (ret != -EPROBE_DEFER)
> > > @@ -382,6 +386,12 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
> > >                                               ret);
> > >                               goto free_genpd_opp;
> > >                       }
> > > +
> > > +                     while (*name) {
> > > +                             pm_runtime_get_sync(*pd_dev);
> > > +                             name++;
> > > +                             pd_dev++;
> > > +                     }
> > >               }
> > >       }
> > >
> > > I really wonder why this doesn't affect CPR (or does it?).
> > > So far I was not able to find anything that would power on/enable
> > > the "cpr" power domain either. But I don't have a qcs404 to verify.
> > >
> > > As far as I can tell from the log, the corner votes are correctly sent
> > > to the RPM now when the CPU frequency is changed.
> > >
> > > However...
> > >
> > > > > > Also: Is there a good way to validate these changes?
> > > > > > I suppose I could check the genpd state but that wouldn't tell me if the
> > > > > > corner was applied correctly. Maybe I can check the actual voltage
> > > > > > through the SPMI interface, hm...
> > > > > >
> > > > >
> > > > > Validating that S2 and VDD_MX changes appropriately in Linux would be a
> > > > > pretty good test.
> > > > >
> > >
> > > Unfortunately I was not able to see any change in the voltage of L3 yet.
> > > On samsung-a5u, /sys/class/regulator/<l3 spmi regulator>/microvolts
> > > permanently reports 1300000 uV, even after a few different corner votes.
> > >
> > > I'm not sure if:
> > >
> > >   - This is normal (maybe some other remoteproc has a higher vote?)
> > >     - I tried to disable wcnss, venus and hexagon without difference
> > >
> > >   - I'm just missing something in the code
> > >
> > >   - This is some peculiarity of the RPM firmware on samsung-a5u.
> > >     (Although that seems quite unlikely to me...)
> > >
> > > Any ideas? :/
> > >
> > > Thanks,
> > > Stephan
> > >
> > > > > > If this seems like a good approach I can split up the changes in
> > > > > > reasonable patches and post it separately. For now the full diff below.
> > > > > >
> > > > >
> > > > > Please do
> > > > >
> > > > > Regards,
> > > > > Bjorn
> > > > >
> > > > > > Stephan
> > > > > >
> > > > > >  arch/arm64/boot/dts/qcom/msm8916.dtsi  | 65 +++++++++++++++++++++++++++++-----
> > > > > >  drivers/cpufreq/cpufreq-dt-platdev.c   |  1 +
> > > > > >  drivers/cpufreq/qcom-cpufreq-nvmem.c   | 11 ++++++
> > > > > >  drivers/soc/qcom/rpmpd.c               | 21 +++++++++++
> > > > > >  include/dt-bindings/power/qcom-rpmpd.h |  7 ++++
> > > > > >  5 files changed, 96 insertions(+), 9 deletions(-)
> > > > > >
> > > > > > diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > > > > > index b0a82447976a..5b8fce8609d0 100644
> > > > > > --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > > > > > +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > > > > > @@ -10,6 +10,7 @@
> > > > > >  #include <dt-bindings/soc/qcom,apr.h>
> > > > > >  #include <dt-bindings/sound/qcom,q6afe.h>
> > > > > >  #include <dt-bindings/thermal/thermal.h>
> > > > > > +#include <dt-bindings/power/qcom-rpmpd.h>
> > > > > >
> > > > > >  / {
> > > > > >         interrupt-parent = <&intc>;
> > > > > > @@ -108,8 +109,8 @@ CPU0: cpu@0 {
> > > > > >                         cpu-supply = <&pm8916_spmi_s2>;
> > > > > >                         operating-points-v2 = <&cpu_opp_table>;
> > > > > >                         #cooling-cells = <2>;
> > > > > > -                       power-domains = <&CPU_PD0>;
> > > > > > -                       power-domain-names = "psci";
> > > > > > +                       power-domains = <&CPU_PD0>, <&rpmpd MSM8916_VDDMX_AO>;
> > > > > > +                       power-domain-names = "psci", "mx";
> > > > > >                 };
> > > > > >
> > > > > >                 CPU1: cpu@1 {
> > > > > > @@ -122,8 +123,8 @@ CPU1: cpu@1 {
> > > > > >                         cpu-supply = <&pm8916_spmi_s2>;
> > > > > >                         operating-points-v2 = <&cpu_opp_table>;
> > > > > >                         #cooling-cells = <2>;
> > > > > > -                       power-domains = <&CPU_PD1>;
> > > > > > -                       power-domain-names = "psci";
> > > > > > +                       power-domains = <&CPU_PD1>, <&rpmpd MSM8916_VDDMX_AO>;
> > > > > > +                       power-domain-names = "psci", "mx";
> > > > > >                 };
> > > > > >
> > > > > >                 CPU2: cpu@2 {
> > > > > > @@ -136,8 +137,8 @@ CPU2: cpu@2 {
> > > > > >                         cpu-supply = <&pm8916_spmi_s2>;
> > > > > >                         operating-points-v2 = <&cpu_opp_table>;
> > > > > >                         #cooling-cells = <2>;
> > > > > > -                       power-domains = <&CPU_PD2>;
> > > > > > -                       power-domain-names = "psci";
> > > > > > +                       power-domains = <&CPU_PD2>, <&rpmpd MSM8916_VDDMX_AO>;
> > > > > > +                       power-domain-names = "psci", "mx";
> > > > > >                 };
> > > > > >
> > > > > >                 CPU3: cpu@3 {
> > > > > > @@ -150,8 +151,8 @@ CPU3: cpu@3 {
> > > > > >                         cpu-supply = <&pm8916_spmi_s2>;
> > > > > >                         operating-points-v2 = <&cpu_opp_table>;
> > > > > >                         #cooling-cells = <2>;
> > > > > > -                       power-domains = <&CPU_PD3>;
> > > > > > -                       power-domain-names = "psci";
> > > > > > +                       power-domains = <&CPU_PD3>, <&rpmpd MSM8916_VDDMX_AO>;
> > > > > > +                       power-domain-names = "psci", "mx";
> > > > > >                 };
> > > > > >
> > > > > >                 L2_0: l2-cache {
> > > > > > @@ -343,40 +344,52 @@ modem_alert0: trip-point@0 {
> > > > > >         };
> > > > > >
> > > > > >         cpu_opp_table: cpu_opp_table {
> > > > > > -               compatible = "operating-points-v2";
> > > > > > +               /*
> > > > > > +                * FIXME: The naming here is really weird, since MSM8916 does
> > > > > > +                * not have kyro. Maybe we should add a more generic compatible?
> > > > > > +                */
> > > > > > +               compatible = "operating-points-v2-kryo-cpu";
> > > > > >                 opp-shared;
> > > > > >
> > > > > >                 opp-200000000 {
> > > > > >                         opp-hz = /bits/ 64 <200000000>;
> > > > > >                         opp-microvolt = <1050000>;
> > > > > > +                       required-opps = <&rpmpd_opp_svs_soc>;
> > > > > >                 };
> > > > > >                 opp-400000000 {
> > > > > >                         opp-hz = /bits/ 64 <400000000>;
> > > > > >                         opp-microvolt = <1050000>;
> > > > > > +                       required-opps = <&rpmpd_opp_svs_soc>;
> > > > > >                 };
> > > > > >                 opp-533330000 {
> > > > > >                         opp-hz = /bits/ 64 <533330000>;
> > > > > >                         opp-microvolt = <1150000>;
> > > > > > +                       required-opps = <&rpmpd_opp_nom>;
> > > > > >                 };
> > > > > >                 opp-800000000 {
> > > > > >                         opp-hz = /bits/ 64 <800000000>;
> > > > > >                         opp-microvolt = <1150000>;
> > > > > > +                       required-opps = <&rpmpd_opp_nom>;
> > > > > >                 };
> > > > > >                 opp-998400000 {
> > > > > >                         opp-hz = /bits/ 64 <998400000>;
> > > > > >                         opp-microvolt = <1350000>;
> > > > > > +                       required-opps = <&rpmpd_opp_super_turbo>;
> > > > > >                 };
> > > > > >                 opp-1094400000 {
> > > > > >                         opp-hz = /bits/ 64 <1094400000>;
> > > > > >                         opp-microvolt = <1350000>;
> > > > > > +                       required-opps = <&rpmpd_opp_super_turbo>;
> > > > > >                 };
> > > > > >                 opp-1152000000 {
> > > > > >                         opp-hz = /bits/ 64 <1152000000>;
> > > > > >                         opp-microvolt = <1350000>;
> > > > > > +                       required-opps = <&rpmpd_opp_super_turbo>;
> > > > > >                 };
> > > > > >                 opp-1209600000 {
> > > > > >                         opp-hz = /bits/ 64 <1209600000>;
> > > > > >                         opp-microvolt = <1350000>;
> > > > > > +                       required-opps = <&rpmpd_opp_super_turbo>;
> > > > > >                 };
> > > > > >         };
> > > > > >
> > > > > > @@ -1710,6 +1723,40 @@ rpmcc: qcom,rpmcc {
> > > > > >                                         #clock-cells = <1>;
> > > > > >                                 };
> > > > > >
> > > > > > +                               rpmpd: power-controller {
> > > > > > +                                       compatible = "qcom,msm8916-rpmpd";
> > > > > > +                                       #power-domain-cells = <1>;
> > > > > > +                                       operating-points-v2 = <&rpmpd_opp_table>;
> > > > > > +
> > > > > > +                                       rpmpd_opp_table: opp-table {
> > > > > > +                                               compatible = "operating-points-v2";
> > > > > > +
> > > > > > +                                               rpmpd_opp_ret: opp1 {
> > > > > > +                                                       opp-level = <1>;
> > > > > > +                                               };
> > > > > > +
> > > > > > +                                               rpmpd_opp_svs: opp2 {
> > > > > > +                                                       opp-level = <2>;
> > > > > > +                                               };
> > > > > > +
> > > > > > +                                               rpmpd_opp_svs_soc: opp3 {
> > > > > > +                                                       opp-level = <3>;
> > > > > > +                                               };
> > > > > > +
> > > > > > +                                               rpmpd_opp_nom: opp4 {
> > > > > > +                                                       opp-level = <4>;
> > > > > > +                                               };
> > > > > > +
> > > > > > +                                               rpmpd_opp_turbo: opp5 {
> > > > > > +                                                       opp-level = <5>;
> > > > > > +                                               };
> > > > > > +
> > > > > > +                                               rpmpd_opp_super_turbo: opp6 {
> > > > > > +                                                       opp-level = <6>;
> > > > > > +                                               };
> > > > > > +                                       };
> > > > > > +                               };
> > > > > > +
> > > > > >                                 smd_rpm_regulators: pm8916-regulators {
> > > > > >                                         compatible = "qcom,rpm-pm8916-regulators";
> > > > > >
> > > > > > diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
> > > > > > index f2ae9cd455c1..b0f6bd0fffc1 100644
> > > > > > --- a/drivers/cpufreq/cpufreq-dt-platdev.c
> > > > > > +++ b/drivers/cpufreq/cpufreq-dt-platdev.c
> > > > > > @@ -128,6 +128,7 @@ static const struct of_device_id blacklist[] __initconst = {
> > > > > >         { .compatible = "nvidia,tegra210", },
> > > > > >
> > > > > >         { .compatible = "qcom,apq8096", },
> > > > > > +       { .compatible = "qcom,msm8916", },
> > > > > >         { .compatible = "qcom,msm8996", },
> > > > > >         { .compatible = "qcom,qcs404", },
> > > > > >
> > > > > > diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > > > > > index f0d2d5035413..c77a30349d08 100644
> > > > > > --- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > > > > > +++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > > > > > @@ -129,6 +129,16 @@ static const struct qcom_cpufreq_match_data match_data_kryo = {
> > > > > >         .get_version = qcom_cpufreq_kryo_name_version,
> > > > > >  };
> > > > > >
> > > > > > +static const char *msm8916_genpd_names[] = { "mx", NULL };
> > > > > > +
> > > > > > +static const struct qcom_cpufreq_match_data match_data_msm8916 = {
> > > > > > +       /*
> > > > > > +        * FIXME: Might need to implement .get_version here to handle
> > > > > > +        * different frequencies depending on speedbin/pvs version.
> > > > > > +        */
> > > > > > +       .genpd_names = msm8916_genpd_names,
> > > > > > +};
> > > > > > +
> > > > > >  static const char *qcs404_genpd_names[] = { "cpr", NULL };
> > > > > >
> > > > > >  static const struct qcom_cpufreq_match_data match_data_qcs404 = {
> > > > > > @@ -301,6 +311,7 @@ static struct platform_driver qcom_cpufreq_driver = {
> > > > > >
> > > > > >  static const struct of_device_id qcom_cpufreq_match_list[] __initconst = {
> > > > > >         { .compatible = "qcom,apq8096", .data = &match_data_kryo },
> > > > > > +       { .compatible = "qcom,msm8916", .data = &match_data_msm8916 },
> > > > > >         { .compatible = "qcom,msm8996", .data = &match_data_kryo },
> > > > > >         { .compatible = "qcom,qcs404", .data = &match_data_qcs404 },
> > > > > >         {},
> > > > > > diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c
> > > > > > index 2b1834c5609a..192ba9099964 100644
> > > > > > --- a/drivers/soc/qcom/rpmpd.c
> > > > > > +++ b/drivers/soc/qcom/rpmpd.c
> > > > > > @@ -115,6 +115,26 @@ struct rpmpd_desc {
> > > > > >
> > > > > >  static DEFINE_MUTEX(rpmpd_lock);
> > > > > >
> > > > > > +/* msm8916 RPM Power Domains */
> > > > > > +DEFINE_RPMPD_PAIR(msm8916, vddcx, vddcx_ao, SMPA, CORNER, 1);
> > > > > > +DEFINE_RPMPD_PAIR(msm8916, vddmx, vddmx_ao, LDOA, CORNER, 3);
> > > > > > +
> > > > > > +DEFINE_RPMPD_VFC(msm8916, vddcx_vfc, SMPA, 1);
> > > > > > +
> > > > > > +static struct rpmpd *msm8916_rpmpds[] = {
> > > > > > +       [MSM8916_VDDCX] =       &msm8916_vddcx,
> > > > > > +       [MSM8916_VDDCX_AO] =    &msm8916_vddcx_ao,
> > > > > > +       [MSM8916_VDDCX_VFC] =   &msm8916_vddcx_vfc,
> > > > > > +       [MSM8916_VDDMX] =       &msm8916_vddmx,
> > > > > > +       [MSM8916_VDDMX_AO] =    &msm8916_vddmx_ao,
> > > > > > +};
> > > > > > +
> > > > > > +static const struct rpmpd_desc msm8916_desc = {
> > > > > > +       .rpmpds = msm8916_rpmpds,
> > > > > > +       .num_pds = ARRAY_SIZE(msm8916_rpmpds),
> > > > > > +       .max_state = MAX_8996_RPMPD_STATE,
> > > > > > +};
> > > > > > +
> > > > > >  /* msm8976 RPM Power Domains */
> > > > > >  DEFINE_RPMPD_PAIR(msm8976, vddcx, vddcx_ao, SMPA, LEVEL, 2);
> > > > > >  DEFINE_RPMPD_PAIR(msm8976, vddmx, vddmx_ao, SMPA, LEVEL, 6);
> > > > > > @@ -220,6 +240,7 @@ static const struct rpmpd_desc qcs404_desc = {
> > > > > >  };
> > > > > >
> > > > > >  static const struct of_device_id rpmpd_match_table[] = {
> > > > > > +       { .compatible = "qcom,msm8916-rpmpd", .data = &msm8916_desc },
> > > > > >         { .compatible = "qcom,msm8976-rpmpd", .data = &msm8976_desc },
> > > > > >         { .compatible = "qcom,msm8996-rpmpd", .data = &msm8996_desc },
> > > > > >         { .compatible = "qcom,msm8998-rpmpd", .data = &msm8998_desc },
> > > > > > diff --git a/include/dt-bindings/power/qcom-rpmpd.h b/include/dt-bindings/power/qcom-rpmpd.h
> > > > > > index 3f74096d5a7c..70d304a2deae 100644
> > > > > > --- a/include/dt-bindings/power/qcom-rpmpd.h
> > > > > > +++ b/include/dt-bindings/power/qcom-rpmpd.h
> > > > > > @@ -51,6 +51,13 @@
> > > > > >  #define RPMH_REGULATOR_LEVEL_TURBO     384
> > > > > >  #define RPMH_REGULATOR_LEVEL_TURBO_L1  416
> > > > > >
> > > > > > +/* MSM8916 Power Domain Indexes */
> > > > > > +#define MSM8916_VDDCX          0
> > > > > > +#define MSM8916_VDDCX_AO       1
> > > > > > +#define MSM8916_VDDCX_VFC      2
> > > > > > +#define MSM8916_VDDMX          3
> > > > > > +#define MSM8916_VDDMX_AO       4
> > > > > > +
> > > > > >  /* MSM8976 Power Domain Indexes */
> > > > > >  #define MSM8976_VDDCX          0
> > > > > >  #define MSM8976_VDDCX_AO       1

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps
  2020-05-08 12:08                 ` Ulf Hansson
  2020-05-08 13:42                   ` Stephan Gerhold
@ 2020-05-11  5:29                   ` Viresh Kumar
  1 sibling, 0 replies; 32+ messages in thread
From: Viresh Kumar @ 2020-05-11  5:29 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Bjorn Andersson, Stephan Gerhold, Loic Poulain, Andy Gross,
	linux-arm-msm, Lina Iyer

On 08-05-20, 14:08, Ulf Hansson wrote:
> + Lina
> 
> On Thu, 7 May 2020 at 07:33, Bjorn Andersson <bjorn.andersson@linaro.org> wrote:
> >
> > On Wed 06 May 14:18 PDT 2020, Stephan Gerhold wrote:
> >
> > Viresh, Ulf,
> >
> > Stephan is trying to describe the relationship between the CPU rail and
> > the memory rail on db410c (where the performance state of the memory
> > rail needs to be kept above the performance state of the CPU supply.
> >
> > The latter is modelled as a power-domain and the performance state
> > changes as expected, but no one enables the power-domain.
> 
> Just to make one thing clear, from a genpd framework point of view,
> power on/off of a genpd is orthogonal to setting/aggregating
> performance states for it.
> 
> It's instead up to the genpd provider to deal with this (as I
> understand, that seems to be the issue from the below discussions).
> 
> >
> > What's the appropriate method for ensuring the power-domain is
> > enabled/disabled as needed? Should it be referenced in the hierarchical
> > power domain for the CPUs perhaps?
> 
> If I understand the dependency correctly, perhaps you are right that
> there needs to be a subdomain assigned. Although, I don't know if this
> ever has been tested to work for a real use case, when it comes to
> performance state propagations upwards in the hierarchy.
> 
> Viresh?

I have modeled that with a fake system, and yes it was tested. But not on real
hardware but it should work nevertheless.

-- 
viresh

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps
  2020-05-07 10:46               ` Stephan Gerhold
@ 2020-05-21 19:18                 ` Stephan Gerhold
  2020-05-23 12:08                   ` Stephan Gerhold
  0 siblings, 1 reply; 32+ messages in thread
From: Stephan Gerhold @ 2020-05-21 19:18 UTC (permalink / raw)
  To: Bjorn Andersson; +Cc: Loic Poulain, agross, linux-arm-msm

On Thu, May 07, 2020 at 12:46:08PM +0200, Stephan Gerhold wrote:
> On Wed, May 06, 2020 at 11:18:07PM +0200, Stephan Gerhold wrote:
> > Hi,
> > 
> > On Sun, Apr 26, 2020 at 02:31:48PM +0200, Stephan Gerhold wrote:
> > > On Wed, Apr 22, 2020 at 09:55:06PM -0700, Bjorn Andersson wrote:
> > > > On Fri 03 Apr 11:00 PDT 2020, Stephan Gerhold wrote:
> > > > 
> > > > > On Fri, Apr 03, 2020 at 12:09:25PM +0200, Stephan Gerhold wrote:
> > > > > > On Thu, Apr 02, 2020 at 06:31:19PM -0700, Bjorn Andersson wrote:
> > > > > > > On Thu 02 Apr 01:13 PDT 2020, Stephan Gerhold wrote:
> > > > > > > 
> > > > > > > > Hi,
> > > > > > > > 
> > > > > > > > On Wed, Apr 01, 2020 at 07:50:59PM +0200, Loic Poulain wrote:
> > > > > > > > > The highest cpu frequency opps have been dropped because CPR is not
> > > > > > > > > supported. However, we can simply specify operating voltage so that
> > > > > > > > > they match the max corner voltages for each freq. With that, we can
> > > > > > > > > support up to 1.36Ghz. Ideally, msm8916 CPR should be implemented to
> > > > > > > > > fine tune operating voltages and optimize power consumption.
> > > > > > > > 
> > > > > > > > Thanks for the patch! I was wondering how to enable the higher CPU
> > > > > > > > frequencies for a while now...
> > > > > > > > 
> > > > > > > > I was actually quite excited to see CPR being mainlined for QCS404.
> > > > > > > > If we are trying to add such a workaround (rather than CPR) for MSM8916
> > > > > > > > now, does that mean it's unlikely to see CPR working for MSM8916
> > > > > > > > anytime soon?
> > > > > > > > 
> > > > > > > > AFAICT, there is a WIP branch from Niklas Cassel here:
> > > > > > > > https://git.linaro.org/people/nicolas.dechesne/niklas.cassel/kernel.git/log/?h=cpr-msm8916-mainline
> > > > > > > > but it hasn't been updated for a while. (Not sure if it was working
> > > > > > > > already...)
> > > > > > > > 
> > > > > > > > Can someone explain what is missing to make CPR work for MSM8916?
> > > > > > > > 
> > > > > > > 
> > > > > > > CPR needs to control 3 things; VDD_APC, VDD_MX and MEMACC. On QCS404 it
> > > > > > > seems we don't have to adjust VDD_MX, so the code for this is missing
> > > > > > > from the driver.
> > > > > > > 
> > > > > > > So, afaict, what's missing is that rpmpd.c needs to gain support for
> > > > > > > 8916, then the CPR driver needs to gain a cpr_acc_desc and compatible
> > > > > > > for 8916, it needs to reference the VDDMX power domain and before/after
> > > > > > > we're adjusting the corner of the CPR we need to adjust the MX according
> > > > > > > to the mapping specified in the downstream kernel (i.e.  1->4, 2->5 and
> > > > > > > 3->7).
> > > > > > > 
> > > > > > > 
> > > > > > > Unfortunately, the requirement that VDDMX (VDD_MEM I presume) must be
> > > > > > > higher than VDD_APC most likely needs to be taken into consideration for
> > > > > > > Loic's proposed static voltage scaling as well. Unless VDD_MEM is left
> > > > > > > in Turbo mode from the boot loader I think we need to take VDDMX to
> > > > > > > corner 7 for speeds 998MHz and above (i.e. where we pull VDD_APC to
> > > > > > > 1.35V).
> > > > > > > 
> > > > > > 
> > > > > > I see! I wonder how hard it would be to add MSM8916 to rpmpd,
> > > > > > looking at previous commits it's mainly setting up a few defines?
> > > > > > 
> > > > > > If I understand it correctly, the OPPs from rpmpd could then be
> > > > > > referenced as "required-opps" in the CPU OPP table so that VDD_MX is
> > > > > > scaled together with the CPU frequency, and doesn't need to stay at
> > > > > > turbo mode (like in v3 from Loic) the whole time.
> > > > > > 
> > > > > 
> > > > > I have been thinking about this some more and I think I came up with
> > > > > some changes that make sense (but not entirely sure).
> > > > > 
> > > > > Based on the available downstream sources I guessed the defines to add
> > > > > for MSM8916 to the rpmpd driver. Then I added the VDD_MX OPPs as
> > > > > "required-opps" to the CPU OPP table so it would vote for the appopriate
> > > > > corners (with the mapping you mentioned above).
> > > > > 
> > > > 
> > > > I was not aware it was possible to describe the dependency between the
> > > > CPU opp table and MX in this fashion. If that's the case then this looks
> > > > really good and it should be straight forward to add MSM8916 support to
> > > > the CPR driver as well.
> > > > 
> > > 
> > > Indeed!
> > > 
> > > > > I haven't tested it yet, maybe I can get some feedback first if the code
> > > > > seems reasonable or if I'm missing something obvious? :)
> > > > > 
> > > > 
> > > > Have you tested this yet?
> > > > 
> > > 
> > > I just did. It does not fully work, yet:
> > > 
> > > rpmpd_set_performance() is indeed called as necessary when switching the
> > > CPU frequency. When I set 200 MHz it sets corner 3, with 533 MHz corner 4
> > > and starting with 998 MHz corner 6. So far so good :)
> > > 
> > > However, there is never actually anything sent to the RPM. :(
> > > It bails out in rpmpd_set_performance() before calling rpmpd_aggregate_corner():
> > > 
> > > 	/* Always send updates for vfc and vfl */
> > > 	if (!pd->enabled && pd->key != KEY_FLOOR_CORNER &&
> > > 	    pd->key != KEY_FLOOR_LEVEL)
> > > 		goto out;
> > > 
> > > Seems like we just try to set performance states, but never actually
> > > enable (rpmpd_power_on()) the power domain (pd->enabled == false).
> > > 
> > > I'm not sure which of the components involved here should handle that.
> > > The OPP core when setting required OPPs, the genpd core etc.
> > >
> > > Any ideas?
> > > 
> > > Thanks,
> > > Stephan
> > > 
> > 
> > For now I have added something to qcom-cpufreq-nvmem.c to power on/enable
> > the power domain (not really sure if it belongs there...):
> > 
> > diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > index a1b8238872a2..ed352ead037e 100644
> > --- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > +++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > @@ -26,6 +26,7 @@
> >  #include <linux/platform_device.h>
> >  #include <linux/pm_domain.h>
> >  #include <linux/pm_opp.h>
> > +#include <linux/pm_runtime.h>
> >  #include <linux/slab.h>
> >  #include <linux/soc/qcom/smem.h>
> >  
> > @@ -370,10 +371,13 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
> >  		}
> >  
> >  		if (drv->data->genpd_names) {
> > +			struct device **pd_dev;
> > +			const char **name = drv->data->genpd_names;
> > +
> >  			drv->genpd_opp_tables[cpu] =
> >  				dev_pm_opp_attach_genpd(cpu_dev,
> >  							drv->data->genpd_names,
> > -							NULL);
> > +							&pd_dev);
> >  			if (IS_ERR(drv->genpd_opp_tables[cpu])) {
> >  				ret = PTR_ERR(drv->genpd_opp_tables[cpu]);
> >  				if (ret != -EPROBE_DEFER)
> > @@ -382,6 +386,12 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
> >  						ret);
> >  				goto free_genpd_opp;
> >  			}
> > +
> > +			while (*name) {
> > +				pm_runtime_get_sync(*pd_dev);
> > +				name++;
> > +				pd_dev++;
> > +			}
> >  		}
> >  	}
> > 
> > I really wonder why this doesn't affect CPR (or does it?).
> > So far I was not able to find anything that would power on/enable
> > the "cpr" power domain either. But I don't have a qcs404 to verify.
> >  
> > As far as I can tell from the log, the corner votes are correctly sent
> > to the RPM now when the CPU frequency is changed.
> > 
> > However...
> > 
> > > > > Also: Is there a good way to validate these changes?
> > > > > I suppose I could check the genpd state but that wouldn't tell me if the
> > > > > corner was applied correctly. Maybe I can check the actual voltage
> > > > > through the SPMI interface, hm...
> > > > > 
> > > > 
> > > > Validating that S2 and VDD_MX changes appropriately in Linux would be a
> > > > pretty good test.
> > > > 
> > 
> > Unfortunately I was not able to see any change in the voltage of L3 yet.
> > On samsung-a5u, /sys/class/regulator/<l3 spmi regulator>/microvolts
> > permanently reports 1300000 uV, even after a few different corner votes.
> > 
> > I'm not sure if:
> > 
> >   - This is normal (maybe some other remoteproc has a higher vote?)
> >     - I tried to disable wcnss, venus and hexagon without difference
> > 
> >   - I'm just missing something in the code
> > 
> >   - This is some peculiarity of the RPM firmware on samsung-a5u.
> >     (Although that seems quite unlikely to me...)
> > 
> > Any ideas? :/
> > 
> 
> I just tried the same on the downstream kernel for samsung-a5u.
> There the L3 voltage doesn't change either, it stays on 1300000 uV
> permanently. So more likely would be either "this is normal" or
> "This is some peculiarity of the RPM firmware on samsung-a5u".
> 
> I don't have a DB410c available for testing, but I'm curious if it would
> work correctly there. So far I have been unable to find any obvious
> mistake in my changes.
> 
> I'm attaching the full diff (including Loic's changes) in case someone
> wants to test this on the DB410c (or some other MSM8916 device).
> Basically you need to:
> 
>   1. CONFIG_QCOM_RPMPD=y
>      CONFIG_ARM_QCOM_CPUFREQ_NVMEM=y
>   2. Run it and change CPU frequencies a bit
>      (either with an automatic CPU governor, or by setting speeds
>       manually with powersave/performance/userspace)
>   3. There should be "set performance state" messages in dmesg
>      for the VDD_MX corner votes
>   4. Identify the spmi l3 regulator using /sys/class/regulator/*/name
>   5. Check the reported voltage in /sys/class/regulator/.../microvolts
> 
> For me it stays on 1300000 uV, permanently. :(
> 

I recently bought another device that does not have signature checks
enabled. For now I have tested with the original firmware there:

With or without my changes it stays at 1287500 uV permanently.
At least this seems somewhat more realistic since this is the
"super turbo" voltage.

I tried disabling various things in case they affect this somehow:
WCNSS in particular sets 1287500 uV for pm8916_l3.
But even with WCNSS disabled, even with the regulator constraints
removed for pm8916_l3 and all changes reverted - it keeps reporting
1287500 uV through the SPMI interface, no matter which CPU frequency
is selected.

This is even more confusing because l3 is still at nominal voltage
(1150000 uV) in the lk bootloader. (I ported a part of the mainline
spmi_regulator driver to lk so I can dump the voltages from there...)
Somehow it gets changed when Linux is booted. Very confusing.

Unlike on my previous test device, testing on downstream was successful:

  - CPU frequency 200MHz - 800MHz results into 1150000 uV
    reported as voltage for l3 through the SPMI interface (corner 4/5)
  - Higher CPU frequencies result into 1287500 uV (corner 7)

Again I ported the spmi_regulator driver from mainline to downstream,
so the way the voltage is read should be the same.

Clearly something must be different/missing in my changes,
but I still have no idea what exactly.
Any suggestions would be highly appreciated :)

Thanks,
Stephan

PS: Does someone know if the RPM firmware on MSM8916 is usually
device-specific? After some funny re-partitioning I managed to get
PSCI working on this device by flashing the HYP/TZ firmware from DB410c.

I was considering also flashing the RPM firmware from DB410c,
but not entirely sure if that would be safe. (Any voltages hardcoded there?)

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps
  2020-05-21 19:18                 ` Stephan Gerhold
@ 2020-05-23 12:08                   ` Stephan Gerhold
  2020-05-27 20:47                     ` Georgi Djakov
  0 siblings, 1 reply; 32+ messages in thread
From: Stephan Gerhold @ 2020-05-23 12:08 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Loic Poulain, agross, linux-arm-msm, Stephen Boyd, Georgi Djakov

+Cc Stephen Boyd, Georgi Djakov

On Thu, May 21, 2020 at 09:18:14PM +0200, Stephan Gerhold wrote:
> On Thu, May 07, 2020 at 12:46:08PM +0200, Stephan Gerhold wrote:
> > On Wed, May 06, 2020 at 11:18:07PM +0200, Stephan Gerhold wrote:
> > > Hi,
> > > 
> > > On Sun, Apr 26, 2020 at 02:31:48PM +0200, Stephan Gerhold wrote:
> > > > On Wed, Apr 22, 2020 at 09:55:06PM -0700, Bjorn Andersson wrote:
> > > > > On Fri 03 Apr 11:00 PDT 2020, Stephan Gerhold wrote:
> > > > > 
> > > > > > On Fri, Apr 03, 2020 at 12:09:25PM +0200, Stephan Gerhold wrote:
> > > > > > > On Thu, Apr 02, 2020 at 06:31:19PM -0700, Bjorn Andersson wrote:
> > > > > > > > On Thu 02 Apr 01:13 PDT 2020, Stephan Gerhold wrote:
> > > > > > > > 
> > > > > > > > > Hi,
> > > > > > > > > 
> > > > > > > > > On Wed, Apr 01, 2020 at 07:50:59PM +0200, Loic Poulain wrote:
> > > > > > > > > > The highest cpu frequency opps have been dropped because CPR is not
> > > > > > > > > > supported. However, we can simply specify operating voltage so that
> > > > > > > > > > they match the max corner voltages for each freq. With that, we can
> > > > > > > > > > support up to 1.36Ghz. Ideally, msm8916 CPR should be implemented to
> > > > > > > > > > fine tune operating voltages and optimize power consumption.
> > > > > > > > > 
> > > > > > > > > Thanks for the patch! I was wondering how to enable the higher CPU
> > > > > > > > > frequencies for a while now...
> > > > > > > > > 
> > > > > > > > > I was actually quite excited to see CPR being mainlined for QCS404.
> > > > > > > > > If we are trying to add such a workaround (rather than CPR) for MSM8916
> > > > > > > > > now, does that mean it's unlikely to see CPR working for MSM8916
> > > > > > > > > anytime soon?
> > > > > > > > > 
> > > > > > > > > AFAICT, there is a WIP branch from Niklas Cassel here:
> > > > > > > > > https://git.linaro.org/people/nicolas.dechesne/niklas.cassel/kernel.git/log/?h=cpr-msm8916-mainline
> > > > > > > > > but it hasn't been updated for a while. (Not sure if it was working
> > > > > > > > > already...)
> > > > > > > > > 
> > > > > > > > > Can someone explain what is missing to make CPR work for MSM8916?
> > > > > > > > > 
> > > > > > > > 
> > > > > > > > CPR needs to control 3 things; VDD_APC, VDD_MX and MEMACC. On QCS404 it
> > > > > > > > seems we don't have to adjust VDD_MX, so the code for this is missing
> > > > > > > > from the driver.
> > > > > > > > 
> > > > > > > > So, afaict, what's missing is that rpmpd.c needs to gain support for
> > > > > > > > 8916, then the CPR driver needs to gain a cpr_acc_desc and compatible
> > > > > > > > for 8916, it needs to reference the VDDMX power domain and before/after
> > > > > > > > we're adjusting the corner of the CPR we need to adjust the MX according
> > > > > > > > to the mapping specified in the downstream kernel (i.e.  1->4, 2->5 and
> > > > > > > > 3->7).
> > > > > > > > 
> > > > > > > > 
> > > > > > > > Unfortunately, the requirement that VDDMX (VDD_MEM I presume) must be
> > > > > > > > higher than VDD_APC most likely needs to be taken into consideration for
> > > > > > > > Loic's proposed static voltage scaling as well. Unless VDD_MEM is left
> > > > > > > > in Turbo mode from the boot loader I think we need to take VDDMX to
> > > > > > > > corner 7 for speeds 998MHz and above (i.e. where we pull VDD_APC to
> > > > > > > > 1.35V).
> > > > > > > > 
> > > > > > > 
> > > > > > > I see! I wonder how hard it would be to add MSM8916 to rpmpd,
> > > > > > > looking at previous commits it's mainly setting up a few defines?
> > > > > > > 
> > > > > > > If I understand it correctly, the OPPs from rpmpd could then be
> > > > > > > referenced as "required-opps" in the CPU OPP table so that VDD_MX is
> > > > > > > scaled together with the CPU frequency, and doesn't need to stay at
> > > > > > > turbo mode (like in v3 from Loic) the whole time.
> > > > > > > 
> > > > > > 
> > > > > > I have been thinking about this some more and I think I came up with
> > > > > > some changes that make sense (but not entirely sure).
> > > > > > 
> > > > > > Based on the available downstream sources I guessed the defines to add
> > > > > > for MSM8916 to the rpmpd driver. Then I added the VDD_MX OPPs as
> > > > > > "required-opps" to the CPU OPP table so it would vote for the appopriate
> > > > > > corners (with the mapping you mentioned above).
> > > > > > 
> > > > > 
> > > > > I was not aware it was possible to describe the dependency between the
> > > > > CPU opp table and MX in this fashion. If that's the case then this looks
> > > > > really good and it should be straight forward to add MSM8916 support to
> > > > > the CPR driver as well.
> > > > > 
> > > > 
> > > > Indeed!
> > > > 
> > > > > > I haven't tested it yet, maybe I can get some feedback first if the code
> > > > > > seems reasonable or if I'm missing something obvious? :)
> > > > > > 
> > > > > 
> > > > > Have you tested this yet?
> > > > > 
> > > > 
> > > > I just did. It does not fully work, yet:
> > > > 
> > > > rpmpd_set_performance() is indeed called as necessary when switching the
> > > > CPU frequency. When I set 200 MHz it sets corner 3, with 533 MHz corner 4
> > > > and starting with 998 MHz corner 6. So far so good :)
> > > > 
> > > > However, there is never actually anything sent to the RPM. :(
> > > > It bails out in rpmpd_set_performance() before calling rpmpd_aggregate_corner():
> > > > 
> > > > 	/* Always send updates for vfc and vfl */
> > > > 	if (!pd->enabled && pd->key != KEY_FLOOR_CORNER &&
> > > > 	    pd->key != KEY_FLOOR_LEVEL)
> > > > 		goto out;
> > > > 
> > > > Seems like we just try to set performance states, but never actually
> > > > enable (rpmpd_power_on()) the power domain (pd->enabled == false).
> > > > 
> > > > I'm not sure which of the components involved here should handle that.
> > > > The OPP core when setting required OPPs, the genpd core etc.
> > > >
> > > > Any ideas?
> > > > 
> > > > Thanks,
> > > > Stephan
> > > > 
> > > 
> > > For now I have added something to qcom-cpufreq-nvmem.c to power on/enable
> > > the power domain (not really sure if it belongs there...):
> > > 
> > > diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > > index a1b8238872a2..ed352ead037e 100644
> > > --- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > > +++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > > @@ -26,6 +26,7 @@
> > >  #include <linux/platform_device.h>
> > >  #include <linux/pm_domain.h>
> > >  #include <linux/pm_opp.h>
> > > +#include <linux/pm_runtime.h>
> > >  #include <linux/slab.h>
> > >  #include <linux/soc/qcom/smem.h>
> > >  
> > > @@ -370,10 +371,13 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
> > >  		}
> > >  
> > >  		if (drv->data->genpd_names) {
> > > +			struct device **pd_dev;
> > > +			const char **name = drv->data->genpd_names;
> > > +
> > >  			drv->genpd_opp_tables[cpu] =
> > >  				dev_pm_opp_attach_genpd(cpu_dev,
> > >  							drv->data->genpd_names,
> > > -							NULL);
> > > +							&pd_dev);
> > >  			if (IS_ERR(drv->genpd_opp_tables[cpu])) {
> > >  				ret = PTR_ERR(drv->genpd_opp_tables[cpu]);
> > >  				if (ret != -EPROBE_DEFER)
> > > @@ -382,6 +386,12 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
> > >  						ret);
> > >  				goto free_genpd_opp;
> > >  			}
> > > +
> > > +			while (*name) {
> > > +				pm_runtime_get_sync(*pd_dev);
> > > +				name++;
> > > +				pd_dev++;
> > > +			}
> > >  		}
> > >  	}
> > > 
> > > I really wonder why this doesn't affect CPR (or does it?).
> > > So far I was not able to find anything that would power on/enable
> > > the "cpr" power domain either. But I don't have a qcs404 to verify.
> > >  
> > > As far as I can tell from the log, the corner votes are correctly sent
> > > to the RPM now when the CPU frequency is changed.
> > > 
> > > However...
> > > 
> > > > > > Also: Is there a good way to validate these changes?
> > > > > > I suppose I could check the genpd state but that wouldn't tell me if the
> > > > > > corner was applied correctly. Maybe I can check the actual voltage
> > > > > > through the SPMI interface, hm...
> > > > > > 
> > > > > 
> > > > > Validating that S2 and VDD_MX changes appropriately in Linux would be a
> > > > > pretty good test.
> > > > > 
> > > 
> > > Unfortunately I was not able to see any change in the voltage of L3 yet.
> > > On samsung-a5u, /sys/class/regulator/<l3 spmi regulator>/microvolts
> > > permanently reports 1300000 uV, even after a few different corner votes.
> > > 
> > > I'm not sure if:
> > > 
> > >   - This is normal (maybe some other remoteproc has a higher vote?)
> > >     - I tried to disable wcnss, venus and hexagon without difference
> > > 
> > >   - I'm just missing something in the code
> > > 
> > >   - This is some peculiarity of the RPM firmware on samsung-a5u.
> > >     (Although that seems quite unlikely to me...)
> > > 
> > > Any ideas? :/
> > > 
> > 
> > I just tried the same on the downstream kernel for samsung-a5u.
> > There the L3 voltage doesn't change either, it stays on 1300000 uV
> > permanently. So more likely would be either "this is normal" or
> > "This is some peculiarity of the RPM firmware on samsung-a5u".
> > 
> > I don't have a DB410c available for testing, but I'm curious if it would
> > work correctly there. So far I have been unable to find any obvious
> > mistake in my changes.
> > 
> > I'm attaching the full diff (including Loic's changes) in case someone
> > wants to test this on the DB410c (or some other MSM8916 device).
> > Basically you need to:
> > 
> >   1. CONFIG_QCOM_RPMPD=y
> >      CONFIG_ARM_QCOM_CPUFREQ_NVMEM=y
> >   2. Run it and change CPU frequencies a bit
> >      (either with an automatic CPU governor, or by setting speeds
> >       manually with powersave/performance/userspace)
> >   3. There should be "set performance state" messages in dmesg
> >      for the VDD_MX corner votes
> >   4. Identify the spmi l3 regulator using /sys/class/regulator/*/name
> >   5. Check the reported voltage in /sys/class/regulator/.../microvolts
> > 
> > For me it stays on 1300000 uV, permanently. :(
> > 
> 
> I recently bought another device that does not have signature checks
> enabled. For now I have tested with the original firmware there:
> 
> With or without my changes it stays at 1287500 uV permanently.
> At least this seems somewhat more realistic since this is the
> "super turbo" voltage.
> 
> I tried disabling various things in case they affect this somehow:
> WCNSS in particular sets 1287500 uV for pm8916_l3.
> But even with WCNSS disabled, even with the regulator constraints
> removed for pm8916_l3 and all changes reverted - it keeps reporting
> 1287500 uV through the SPMI interface, no matter which CPU frequency
> is selected.
> 
> This is even more confusing because l3 is still at nominal voltage
> (1150000 uV) in the lk bootloader. (I ported a part of the mainline
> spmi_regulator driver to lk so I can dump the voltages from there...)
> Somehow it gets changed when Linux is booted. Very confusing.
> 
> Unlike on my previous test device, testing on downstream was successful:
> 
>   - CPU frequency 200MHz - 800MHz results into 1150000 uV
>     reported as voltage for l3 through the SPMI interface (corner 4/5)
>   - Higher CPU frequencies result into 1287500 uV (corner 7)
> 
> Again I ported the spmi_regulator driver from mainline to downstream,
> so the way the voltage is read should be the same.
> 
> Clearly something must be different/missing in my changes,
> but I still have no idea what exactly.
> Any suggestions would be highly appreciated :)
> 

After several hours of debugging I finally figured out what's wrong:

I guess there are various dependencies on the VDD_CX/VDD_MX
voltage rails in the RPM: VDD_MX will be always higher than VDD_CX,
and VDD_CX is also influenced by some of the clocks.

If I disable the rpmcc/clk-smd-rpm entirely in the device tree,
suddenly the VDD_MX voltage scales correctly with my changes.

This seems to happen because the clk-smd-rpm forces all clocks to
maximum state in the clk_smd_rpm_handoff() function. In my case,
the clocks used for interconnect cause VDD_CX to scale to "super turbo",
which in turn keeps VDD_MX on "super turbo" as well.

I imagine this will be solved properly once we enable the interconnect
driver and all the necessary consumers.

But in general, I think this "handoff" behavior clk-smd-rpm is a bit
weird: As far as I understand, the clock framework normally disables
unused clocks shortly after the boot is complete.

The clk-smd-rpm driver does the opposite: it forces all clocks to on,
to maximum rate and does not seem to report that to the clock framework.
If there is no consumer for the clock it seems to stay on and on maximum
frequency forever.

For example, in order to avoid other remoteprocs influencing the
VDD_CX/VDD_MX voting I have disabled all additional remoteprocs in the
device tree (e.g. WCNSS, venus, ...)

Before Linux is booted (dumped from the PMIC registers in the lk
bootloader), the rf_clk1/2 (modem/wcnss) is off. With clk-smd-rpm
disabled it stays off too. However, when clk-smd-rpm is loaded that
"handoff" function forces them on, and they're never turned off again.

This is invisible to the clock framework - according to the clock
debugfs they are off. But reading the PMIC registers reveals they are on.

I suppose that behavior makes sense for the interconnect clocks,
disabling those without an interconnect driver wouldn't do much good.
But for the other clocks that doesn't seem quite right to me.

What do you think?

Thanks,
Stephan

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps
  2020-04-23  4:55         ` Bjorn Andersson
  2020-04-26 12:31           ` Stephan Gerhold
@ 2020-05-25 15:32           ` Niklas Cassel
  2020-05-25 16:36             ` Stephan Gerhold
  1 sibling, 1 reply; 32+ messages in thread
From: Niklas Cassel @ 2020-05-25 15:32 UTC (permalink / raw)
  To: Bjorn Andersson; +Cc: Stephan Gerhold, Loic Poulain, agross, linux-arm-msm

On Wed, Apr 22, 2020 at 09:55:06PM -0700, Bjorn Andersson wrote:
> > Based on the available downstream sources I guessed the defines to add
> > for MSM8916 to the rpmpd driver. Then I added the VDD_MX OPPs as
> > "required-opps" to the CPU OPP table so it would vote for the appopriate
> > corners (with the mapping you mentioned above).
> > 
> 
> I was not aware it was possible to describe the dependency between the
> CPU opp table and MX in this fashion. If that's the case then this looks
> really good and it should be straight forward to add MSM8916 support to
> the CPR driver as well.
> 
> > I haven't tested it yet, maybe I can get some feedback first if the code
> > seems reasonable or if I'm missing something obvious? :)
> > 
> 
> Have you tested this yet?
> 
> > Also: Is there a good way to validate these changes?
> > I suppose I could check the genpd state but that wouldn't tell me if the
> > corner was applied correctly. Maybe I can check the actual voltage
> > through the SPMI interface, hm...
> > 
> 
> Validating that S2 and VDD_MX changes appropriately in Linux would be a
> pretty good test.

Like Bjorn says,

Downstream CPR on MSM8916 controls 3 things; VDD_APC, VDD_MX and MEMACC.

On QCS404 we don't have to adjust VDD_MX, therefore this is no code for
this in the upstream CPR driver. It just scales VPP_APC and MEMACC.

I like Stephan's idea of scaling VDD_APC and VDD_MEM to the maximum
necessary for the selected CPU frequency, until there is full CPR
support for MSM8916 (if ever).


The patch suggested so far looks good, however, I'm slightly worried
that this might lead to unstable boards, since MEMACC is never scaled
in the suggested patch.

Perhaps someone could ask Qualcomm nicely if this is really required.
Last time I talked to a Qualcomm engineer, he claimed that it was
needed, but I remember that his response was a bit ambiguous.


Kind regards,
Niklas

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps
  2020-05-25 15:32           ` Niklas Cassel
@ 2020-05-25 16:36             ` Stephan Gerhold
  2020-05-25 19:44               ` Niklas Cassel
  0 siblings, 1 reply; 32+ messages in thread
From: Stephan Gerhold @ 2020-05-25 16:36 UTC (permalink / raw)
  To: Niklas Cassel; +Cc: Bjorn Andersson, Loic Poulain, agross, linux-arm-msm

On Mon, May 25, 2020 at 05:32:47PM +0200, Niklas Cassel wrote:
> On Wed, Apr 22, 2020 at 09:55:06PM -0700, Bjorn Andersson wrote:
> > > Based on the available downstream sources I guessed the defines to add
> > > for MSM8916 to the rpmpd driver. Then I added the VDD_MX OPPs as
> > > "required-opps" to the CPU OPP table so it would vote for the appopriate
> > > corners (with the mapping you mentioned above).
> > > 
> > 
> > I was not aware it was possible to describe the dependency between the
> > CPU opp table and MX in this fashion. If that's the case then this looks
> > really good and it should be straight forward to add MSM8916 support to
> > the CPR driver as well.
> > 
> > > I haven't tested it yet, maybe I can get some feedback first if the code
> > > seems reasonable or if I'm missing something obvious? :)
> > > 
> > 
> > Have you tested this yet?
> > 
> > > Also: Is there a good way to validate these changes?
> > > I suppose I could check the genpd state but that wouldn't tell me if the
> > > corner was applied correctly. Maybe I can check the actual voltage
> > > through the SPMI interface, hm...
> > > 
> > 
> > Validating that S2 and VDD_MX changes appropriately in Linux would be a
> > pretty good test.
> 
> Like Bjorn says,
> 
> Downstream CPR on MSM8916 controls 3 things; VDD_APC, VDD_MX and MEMACC.
> 
> On QCS404 we don't have to adjust VDD_MX, therefore this is no code for
> this in the upstream CPR driver. It just scales VPP_APC and MEMACC.
> 
> I like Stephan's idea of scaling VDD_APC and VDD_MEM to the maximum
> necessary for the selected CPU frequency, until there is full CPR
> support for MSM8916 (if ever).
> 
> 
> The patch suggested so far looks good, however, I'm slightly worried
> that this might lead to unstable boards, since MEMACC is never scaled
> in the suggested patch.
> 

Yeah, I was recently looking at that. I have no idea if it's needed.

If I understand this correctly, on downstream this is implemented
separately as "mem-acc-regulator", although it is controlled by the
"cpr-regulator" driver.

The mapping seems to be fairly static:
Essentially it is just set to Nominal (1), SVS (2) or Turbo (3),
depending on the CPU frequency. (On downstream this is specified in the
device tree as qcom,cpr-corner-map = <1 1 2 2 3 3 3 3 3>; where each
value is one CPU frequency.)

Additionally there seem to be some fuses to eventually override
that behavior slightly (qcom,override-corner-acc-map).
See: https://source.codeaurora.org/quic/la/kernel/msm-3.10/tree/arch/arm/boot/dts/qcom/msm8916-regulator.dtsi?h=LA.BR.1.2.9.1-02310-8x16.0#n29

On mainline this is currently entirely handled by the CPR driver,
and the register sequence for QCS404 actually looks a bit more
complicated... Hmm.

The reason I mention all this: At least as I understand it,
this isn't much different from the VDD_MX scaling. Essentially it
doesn't strictly have something to do with the voltage scaling
we do for CPR (VDD_APC), but rather it seems to be just another
requirement when scaling the CPU frequency.

In other words, I wonder if we should separate this into yet another
power domain driver, and then reference it independently from CPR
as additional required-opps for both MSM8916 and QCS404.

CPR would then be only responsible for the actual adaptive voltage
scaling of VDD_APC.

Does that make sense?

Thanks,
Stephan

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps
  2020-05-25 16:36             ` Stephan Gerhold
@ 2020-05-25 19:44               ` Niklas Cassel
  2020-05-26  8:59                 ` Stephan Gerhold
  0 siblings, 1 reply; 32+ messages in thread
From: Niklas Cassel @ 2020-05-25 19:44 UTC (permalink / raw)
  To: Stephan Gerhold; +Cc: Bjorn Andersson, Loic Poulain, agross, linux-arm-msm

On Mon, May 25, 2020 at 06:36:38PM +0200, Stephan Gerhold wrote:
> On Mon, May 25, 2020 at 05:32:47PM +0200, Niklas Cassel wrote:
> > On Wed, Apr 22, 2020 at 09:55:06PM -0700, Bjorn Andersson wrote:
> > > > Based on the available downstream sources I guessed the defines to add
> > > > for MSM8916 to the rpmpd driver. Then I added the VDD_MX OPPs as
> > > > "required-opps" to the CPU OPP table so it would vote for the appopriate
> > > > corners (with the mapping you mentioned above).
> > > > 
> > > 
> > > I was not aware it was possible to describe the dependency between the
> > > CPU opp table and MX in this fashion. If that's the case then this looks
> > > really good and it should be straight forward to add MSM8916 support to
> > > the CPR driver as well.
> > > 
> > > > I haven't tested it yet, maybe I can get some feedback first if the code
> > > > seems reasonable or if I'm missing something obvious? :)
> > > > 
> > > 
> > > Have you tested this yet?
> > > 
> > > > Also: Is there a good way to validate these changes?
> > > > I suppose I could check the genpd state but that wouldn't tell me if the
> > > > corner was applied correctly. Maybe I can check the actual voltage
> > > > through the SPMI interface, hm...
> > > > 
> > > 
> > > Validating that S2 and VDD_MX changes appropriately in Linux would be a
> > > pretty good test.
> > 
> > Like Bjorn says,
> > 
> > Downstream CPR on MSM8916 controls 3 things; VDD_APC, VDD_MX and MEMACC.
> > 
> > On QCS404 we don't have to adjust VDD_MX, therefore this is no code for
> > this in the upstream CPR driver. It just scales VPP_APC and MEMACC.
> > 
> > I like Stephan's idea of scaling VDD_APC and VDD_MEM to the maximum
> > necessary for the selected CPU frequency, until there is full CPR
> > support for MSM8916 (if ever).
> > 
> > 
> > The patch suggested so far looks good, however, I'm slightly worried
> > that this might lead to unstable boards, since MEMACC is never scaled
> > in the suggested patch.
> > 
> 
> Yeah, I was recently looking at that. I have no idea if it's needed.
> 
> If I understand this correctly, on downstream this is implemented
> separately as "mem-acc-regulator", although it is controlled by the
> "cpr-regulator" driver.
> 
> The mapping seems to be fairly static:
> Essentially it is just set to Nominal (1), SVS (2) or Turbo (3),
> depending on the CPU frequency. (On downstream this is specified in the
> device tree as qcom,cpr-corner-map = <1 1 2 2 3 3 3 3 3>; where each
> value is one CPU frequency.)
> 
> Additionally there seem to be some fuses to eventually override
> that behavior slightly (qcom,override-corner-acc-map).
> See: https://source.codeaurora.org/quic/la/kernel/msm-3.10/tree/arch/arm/boot/dts/qcom/msm8916-regulator.dtsi?h=LA.BR.1.2.9.1-02310-8x16.0#n29
> 
> On mainline this is currently entirely handled by the CPR driver,
> and the register sequence for QCS404 actually looks a bit more
> complicated... Hmm.

I agree:
https://source.codeaurora.org/quic/la/kernel/msm-4.14/tree/arch/arm64/boot/dts/qcom/qcs405-regulator.dtsi?h=msm-4.14#n294

> 
> The reason I mention all this: At least as I understand it,
> this isn't much different from the VDD_MX scaling. Essentially it
> doesn't strictly have something to do with the voltage scaling
> we do for CPR (VDD_APC), but rather it seems to be just another
> requirement when scaling the CPU frequency.

I agree.

> 
> In other words, I wonder if we should separate this into yet another
> power domain driver, and then reference it independently from CPR
> as additional required-opps for both MSM8916 and QCS404.

While this sounds very nice, by simply referencing these as
required-opps, I don't see how the OPP library will be able
to set APC, MX and MEMACC in the correct order:

https://source.codeaurora.org/quic/la/kernel/msm-4.14/tree/drivers/regulator/cpr-regulator.c?h=msm-4.14#n774

If scaling down, first MEMACC is set, then APC is set, then MX is set.

If scaling up, first MX is set, then APC is set, then MEMACC is set.



Perhaps the easiest way is to write a minimalistic cpufreq driver,
very similar to drivers/cpufreq/omap-cpufreq.c, that implements
the .target_index callback, and just like omap_target(), simply
gets the OPP using dev_pm_opp_find_freq_ceil(), and then calls
regulator_set_voltage() (APC), clk_set_rate() (to change the clock
frequency), dev_pm_genpd_set_performance_state() (to set MX),
and then do that little code that needs to be done for memacc.

Considering that CPR is not an actual power domain, CPR gives
adjustments to VDD_APC, but I don't know of any other device
connected to VDD_APC, other than the CPU, so in hindsight the CPR
driver probably should have been implemented using .target_index(),
rather than as a power domain provider using performance states.


Kind regards,
Niklas

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps
  2020-05-25 19:44               ` Niklas Cassel
@ 2020-05-26  8:59                 ` Stephan Gerhold
  2020-05-26 15:54                   ` Niklas Cassel
  0 siblings, 1 reply; 32+ messages in thread
From: Stephan Gerhold @ 2020-05-26  8:59 UTC (permalink / raw)
  To: Niklas Cassel; +Cc: Bjorn Andersson, Loic Poulain, agross, linux-arm-msm

On Mon, May 25, 2020 at 09:44:43PM +0200, Niklas Cassel wrote:
> On Mon, May 25, 2020 at 06:36:38PM +0200, Stephan Gerhold wrote:
> > On Mon, May 25, 2020 at 05:32:47PM +0200, Niklas Cassel wrote:
> > > On Wed, Apr 22, 2020 at 09:55:06PM -0700, Bjorn Andersson wrote:
> > > > > Based on the available downstream sources I guessed the defines to add
> > > > > for MSM8916 to the rpmpd driver. Then I added the VDD_MX OPPs as
> > > > > "required-opps" to the CPU OPP table so it would vote for the appopriate
> > > > > corners (with the mapping you mentioned above).
> > > > > 
> > > > 
> > > > I was not aware it was possible to describe the dependency between the
> > > > CPU opp table and MX in this fashion. If that's the case then this looks
> > > > really good and it should be straight forward to add MSM8916 support to
> > > > the CPR driver as well.
> > > > 
> > > > > I haven't tested it yet, maybe I can get some feedback first if the code
> > > > > seems reasonable or if I'm missing something obvious? :)
> > > > > 
> > > > 
> > > > Have you tested this yet?
> > > > 
> > > > > Also: Is there a good way to validate these changes?
> > > > > I suppose I could check the genpd state but that wouldn't tell me if the
> > > > > corner was applied correctly. Maybe I can check the actual voltage
> > > > > through the SPMI interface, hm...
> > > > > 
> > > > 
> > > > Validating that S2 and VDD_MX changes appropriately in Linux would be a
> > > > pretty good test.
> > > 
> > > Like Bjorn says,
> > > 
> > > Downstream CPR on MSM8916 controls 3 things; VDD_APC, VDD_MX and MEMACC.
> > > 
> > > On QCS404 we don't have to adjust VDD_MX, therefore this is no code for
> > > this in the upstream CPR driver. It just scales VPP_APC and MEMACC.
> > > 
> > > I like Stephan's idea of scaling VDD_APC and VDD_MEM to the maximum
> > > necessary for the selected CPU frequency, until there is full CPR
> > > support for MSM8916 (if ever).
> > > 
> > > 
> > > The patch suggested so far looks good, however, I'm slightly worried
> > > that this might lead to unstable boards, since MEMACC is never scaled
> > > in the suggested patch.
> > > 
> > 
> > Yeah, I was recently looking at that. I have no idea if it's needed.
> > 
> > If I understand this correctly, on downstream this is implemented
> > separately as "mem-acc-regulator", although it is controlled by the
> > "cpr-regulator" driver.
> > 
> > The mapping seems to be fairly static:
> > Essentially it is just set to Nominal (1), SVS (2) or Turbo (3),
> > depending on the CPU frequency. (On downstream this is specified in the
> > device tree as qcom,cpr-corner-map = <1 1 2 2 3 3 3 3 3>; where each
> > value is one CPU frequency.)
> > 
> > Additionally there seem to be some fuses to eventually override
> > that behavior slightly (qcom,override-corner-acc-map).
> > See: https://source.codeaurora.org/quic/la/kernel/msm-3.10/tree/arch/arm/boot/dts/qcom/msm8916-regulator.dtsi?h=LA.BR.1.2.9.1-02310-8x16.0#n29
> > 
> > On mainline this is currently entirely handled by the CPR driver,
> > and the register sequence for QCS404 actually looks a bit more
> > complicated... Hmm.
> 
> I agree:
> https://source.codeaurora.org/quic/la/kernel/msm-4.14/tree/arch/arm64/boot/dts/qcom/qcs405-regulator.dtsi?h=msm-4.14#n294
> 
> > 
> > The reason I mention all this: At least as I understand it,
> > this isn't much different from the VDD_MX scaling. Essentially it
> > doesn't strictly have something to do with the voltage scaling
> > we do for CPR (VDD_APC), but rather it seems to be just another
> > requirement when scaling the CPU frequency.
> 
> I agree.
> 
> > 
> > In other words, I wonder if we should separate this into yet another
> > power domain driver, and then reference it independently from CPR
> > as additional required-opps for both MSM8916 and QCS404.
> 
> While this sounds very nice, by simply referencing these as
> required-opps, I don't see how the OPP library will be able
> to set APC, MX and MEMACC in the correct order:
> 
> https://source.codeaurora.org/quic/la/kernel/msm-4.14/tree/drivers/regulator/cpr-regulator.c?h=msm-4.14#n774
> 
> If scaling down, first MEMACC is set, then APC is set, then MX is set.
> 
> If scaling up, first MX is set, then APC is set, then MEMACC is set.
> 

Indeed, I was also thinking about this.

In general, I'm not sure if this is that much of a problem
for the following reason:

The OPP core code already has well-defined semantics to ensure required
OPPs/regulators are set before/after the frequency change, depending on
if we scale up or down, see e.g.

  https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/opp/core.c#n885

If you specify multiple "required-opps" I think in general the order
will be either irrelevant, or you want to do them in a particular order
for some reason.

If you want to do them in a particular order, then likely because there
is some dependency between them, i.e. here we could say (to some extent)
MEMACC depends on APC, which again depends on MX.

If there is such a dependency I think you almost certainly want to apply
required OPPs in reverse order when scaling down.

I wonder if we could just implement these semantics in the OPP core.
It should be pretty simple, just add a boolean parameter to the
_set_required_opps() function (that says if we're scaling down)
and then iterate over the required OPPs in reverse order.

  https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/opp/core.c#n745

This would result in the correct order iff CPR is used, because you
could set required-opps = <&mx_opp &cpr_opp &mem_acc_opp>;

When scaling up you would get MX -> CPR (APC) -> MEMACC,
when scaling down the reverse MEMACC -> CPR (APC) -> MX.

This would not result in the correct order if we use opp-microvolts
to scale VDD_APC. The regulator is handled separately, so you would
get MX -> MEMACC -> APC, APC -> MEMACC -> MX instead. Oh well.

> 
> Perhaps the easiest way is to write a minimalistic cpufreq driver,
> very similar to drivers/cpufreq/omap-cpufreq.c, that implements
> the .target_index callback, and just like omap_target(), simply
> gets the OPP using dev_pm_opp_find_freq_ceil(), and then calls
> regulator_set_voltage() (APC), clk_set_rate() (to change the clock
> frequency), dev_pm_genpd_set_performance_state() (to set MX),
> and then do that little code that needs to be done for memacc.
> 

I general I like the way these "requirements" for switching to a
particular CPU frequency can be described fully from the device tree.
The omap-cpufreq code definitely has some duplication with the code
I have seen in the OPP core.

But yes, a generic approach like the "required-opps" can only work up
to some extent - if we have too many requirements for particular order
etc a custom cpufreq driver would have probably been easier.

> Considering that CPR is not an actual power domain, CPR gives
> adjustments to VDD_APC, but I don't know of any other device
> connected to VDD_APC, other than the CPU, so in hindsight the CPR
> driver probably should have been implemented using .target_index(),
> rather than as a power domain provider using performance states.

I suppose having CPR, MEMACC etc as power domain providers is a bit
overkill, given there is just one consumer. However, at least the
"performance state" part fits quite well in my opinion. At the end
all these requirements represent some performance state that must be
set when the CPU frequency is changed.

Stephan

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps
  2020-05-26  8:59                 ` Stephan Gerhold
@ 2020-05-26 15:54                   ` Niklas Cassel
  2020-05-26 20:54                     ` Stephan Gerhold
  0 siblings, 1 reply; 32+ messages in thread
From: Niklas Cassel @ 2020-05-26 15:54 UTC (permalink / raw)
  To: Stephan Gerhold; +Cc: Bjorn Andersson, Loic Poulain, agross, linux-arm-msm

On Tue, May 26, 2020 at 10:59:48AM +0200, Stephan Gerhold wrote:
> > Considering that CPR is not an actual power domain, CPR gives
> > adjustments to VDD_APC, but I don't know of any other device
> > connected to VDD_APC, other than the CPU, so in hindsight the CPR
> > driver probably should have been implemented using .target_index(),
> > rather than as a power domain provider using performance states.
> 
> I suppose having CPR, MEMACC etc as power domain providers is a bit
> overkill, given there is just one consumer. However, at least the
> "performance state" part fits quite well in my opinion. At the end
> all these requirements represent some performance state that must be
> set when the CPU frequency is changed.
> 

For MX, it makes sense to model it as a power domain provider, and for
it to have its own OPP table, since this actually is a power domain.

For CPR, I think that the target_index() model of just giving an index
in a frequency table is much better, the OPP library can still be used
to get the frequencies/frequency_table.
Since at least for Qualcom CPU's, the corner (opp-level) is defined as
an increasing number 1,2,3,4, without skips.

Even if it wasn't always without skips, we could just put opp-level in
the CPU opp table, and get it from there.

The only thing that the corner is used for really, is to use it as an
index the local drv->corner array, which is where the (current) VDD_APC
voltage is stored for each index/corner.

For CPR, the .target_index() in cpufreq-dt.c gets called, which is
supplied with an index, but the index gets converted to a frequency.
This frequency is then sent to the OPP library, and is then converted
back to an index of the same value (just increased by one), before
cpr_set_performance_state() is called (which then has to subtract one).
In this case, all the extra overhead of going via genpd is totally
unnecessary.

This is totally correct when setting a performance state on a power
domain like MX, since for an actual power domain you might have
multiple consumers, so you need to go via genpd.

Considering that CPR is not a power domain, I wish the driver wasn't
designed around performance states, which, _for the CPR case_,
is misleading, unnecessary, and adds extra overhead for no reason.

I realize the irony of me criticizing my own code.
I simply know better now, and wish I had designed it differently :)


Kind regards,
Niklas

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps
  2020-05-26 15:54                   ` Niklas Cassel
@ 2020-05-26 20:54                     ` Stephan Gerhold
  2020-05-27 10:39                       ` Niklas Cassel
  0 siblings, 1 reply; 32+ messages in thread
From: Stephan Gerhold @ 2020-05-26 20:54 UTC (permalink / raw)
  To: Niklas Cassel; +Cc: Bjorn Andersson, Loic Poulain, agross, linux-arm-msm

On Tue, May 26, 2020 at 05:54:20PM +0200, Niklas Cassel wrote:
> On Tue, May 26, 2020 at 10:59:48AM +0200, Stephan Gerhold wrote:
> > > Considering that CPR is not an actual power domain, CPR gives
> > > adjustments to VDD_APC, but I don't know of any other device
> > > connected to VDD_APC, other than the CPU, so in hindsight the CPR
> > > driver probably should have been implemented using .target_index(),
> > > rather than as a power domain provider using performance states.
> > 
> > I suppose having CPR, MEMACC etc as power domain providers is a bit
> > overkill, given there is just one consumer. However, at least the
> > "performance state" part fits quite well in my opinion. At the end
> > all these requirements represent some performance state that must be
> > set when the CPU frequency is changed.
> > 
> 
> For MX, it makes sense to model it as a power domain provider, and for
> it to have its own OPP table, since this actually is a power domain.
> 
> For CPR, I think that the target_index() model of just giving an index
> in a frequency table is much better, the OPP library can still be used
> to get the frequencies/frequency_table.
> Since at least for Qualcom CPU's, the corner (opp-level) is defined as
> an increasing number 1,2,3,4, without skips.
> 
> Even if it wasn't always without skips, we could just put opp-level in
> the CPU opp table, and get it from there.
> 
> The only thing that the corner is used for really, is to use it as an
> index the local drv->corner array, which is where the (current) VDD_APC
> voltage is stored for each index/corner.
> 
> For CPR, the .target_index() in cpufreq-dt.c gets called, which is
> supplied with an index, but the index gets converted to a frequency.
> This frequency is then sent to the OPP library, and is then converted
> back to an index of the same value (just increased by one), before
> cpr_set_performance_state() is called (which then has to subtract one).
> In this case, all the extra overhead of going via genpd is totally
> unnecessary.
> 
> This is totally correct when setting a performance state on a power
> domain like MX, since for an actual power domain you might have
> multiple consumers, so you need to go via genpd.
> 
> Considering that CPR is not a power domain, I wish the driver wasn't
> designed around performance states, which, _for the CPR case_,
> is misleading, unnecessary, and adds extra overhead for no reason.
> 
> I realize the irony of me criticizing my own code.
> I simply know better now, and wish I had designed it differently :)
> 

I see what you mean. I'm not sure how much of a problem the "genpd
overhead" really is in practice (although I assume it's called quite
frequently with a dynamic CPU frequency governor). There is also the
argument of it being slightly misleading (because CPR is not actually
a real power domain).

Speaking of the current solution, I also have to say that (IMO) the
device tree binding for "required-opps" is rather confusing
and potentially misleading.

e.g. for VDD_MX scaling I use

	required-opps = <&rpmpd_opp_nom>;

but looking at just the OPP table absolutely nothing tells me this is
supposed to apply to VDD_MX. You actually need to go search for the cpu@
device tree node and then know that some of the power domains there
(in some order) are eventually going to be used for the required-opps
there. The order is only defined by the qcom-nvmem-cpufreq driver.

It took me a few hours to get that right... :)

Nevertheless I guess we need a solution for scaling MEMACC without CPR
for now. :) I'm not sure if rewriting all this is very realistic
(if even possible). So I guess we might be stuck with the genpd approach?

Thanks,
Stephan

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps
  2020-05-26 20:54                     ` Stephan Gerhold
@ 2020-05-27 10:39                       ` Niklas Cassel
  2020-05-27 12:04                         ` Stephan Gerhold
  0 siblings, 1 reply; 32+ messages in thread
From: Niklas Cassel @ 2020-05-27 10:39 UTC (permalink / raw)
  To: Stephan Gerhold; +Cc: Bjorn Andersson, Loic Poulain, agross, linux-arm-msm

On Tue, May 26, 2020 at 10:54:03PM +0200, Stephan Gerhold wrote:
> Speaking of the current solution, I also have to say that (IMO) the
> device tree binding for "required-opps" is rather confusing
> and potentially misleading.
> 
> e.g. for VDD_MX scaling I use
> 
> 	required-opps = <&rpmpd_opp_nom>;
> 
> but looking at just the OPP table absolutely nothing tells me this is
> supposed to apply to VDD_MX. You actually need to go search for the cpu@
> device tree node and then know that some of the power domains there
> (in some order) are eventually going to be used for the required-opps
> there. The order is only defined by the qcom-nvmem-cpufreq driver.
> 
> It took me a few hours to get that right... :)
> 
> Nevertheless I guess we need a solution for scaling MEMACC without CPR
> for now. :) I'm not sure if rewriting all this is very realistic
> (if even possible). So I guess we might be stuck with the genpd approach?

I agree, the CPR driver will most likely not be changed now, since we
need to be compatible with the existing device tree.


For DVFS without CPR:

You need to scale APC, MX, MEMACC.

If we don't care about MEMACC, then the existing code in the OPP library
satisfies all our needs.
The problem here is if we need to do MEMACC as well.

I don't think it is proper to implement MEMACC as a power domain
(because it is not). Thus, we can't add it as a required-opp.

Another problem is that MEMACC should be done after regulator_set_voltage()
when scaling up, and before regulator_set_voltage() when scaling down.

So even if MEMACC was a power domain, currently the OPP library does
the _set_required_opps() call in the wrong order needed for MEMACC.

Like you said, the OPP library almost does everything already,
so it probably makes most sense to extend it to your needs,
rather than duplicating most of the code inside dev_pm_opp_set_rate().


I guess what you really want is two new optional callbacks in
dev_pm_opp_set_rate(), one before _generic_set_opp_regulator() and one
after, where you could do the MEMACC thing.

The callbacks need to have a parameter that tells if we are scaling down
or up.

Or, if Viresh doesn't like new function pointers, create a new
OPP_EVENT_* that you can register for, and in that callback you do what
you need.

Or, maybe you can even use the existing CPUFREQ_TRANSITION_NOTIFIER,
with CPUFREQ_PRECHANGE / CPUFREQ_POSTCHANGE, however, I'm not sure
how nicely they play when you are using the OPP library.


Kind regards,
Niklas

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps
  2020-05-27 10:39                       ` Niklas Cassel
@ 2020-05-27 12:04                         ` Stephan Gerhold
  2020-05-27 12:59                           ` Niklas Cassel
  2020-05-28  4:44                           ` Viresh Kumar
  0 siblings, 2 replies; 32+ messages in thread
From: Stephan Gerhold @ 2020-05-27 12:04 UTC (permalink / raw)
  To: Niklas Cassel
  Cc: Bjorn Andersson, Loic Poulain, agross, linux-arm-msm, Viresh Kumar

+Cc Viresh (should have already done this earlier :) )

On Wed, May 27, 2020 at 12:39:21PM +0200, Niklas Cassel wrote:
> On Tue, May 26, 2020 at 10:54:03PM +0200, Stephan Gerhold wrote:
> > Speaking of the current solution, I also have to say that (IMO) the
> > device tree binding for "required-opps" is rather confusing
> > and potentially misleading.
> > 
> > e.g. for VDD_MX scaling I use
> > 
> > 	required-opps = <&rpmpd_opp_nom>;
> > 
> > but looking at just the OPP table absolutely nothing tells me this is
> > supposed to apply to VDD_MX. You actually need to go search for the cpu@
> > device tree node and then know that some of the power domains there
> > (in some order) are eventually going to be used for the required-opps
> > there. The order is only defined by the qcom-nvmem-cpufreq driver.
> > 
> > It took me a few hours to get that right... :)
> > 
> > Nevertheless I guess we need a solution for scaling MEMACC without CPR
> > for now. :) I'm not sure if rewriting all this is very realistic
> > (if even possible). So I guess we might be stuck with the genpd approach?
> 
> I agree, the CPR driver will most likely not be changed now, since we
> need to be compatible with the existing device tree.
> 
> 
> For DVFS without CPR:
> 
> You need to scale APC, MX, MEMACC.
> 
> If we don't care about MEMACC, then the existing code in the OPP library
> satisfies all our needs.
> The problem here is if we need to do MEMACC as well.
> 
> I don't think it is proper to implement MEMACC as a power domain
> (because it is not). Thus, we can't add it as a required-opp.
> 
> Another problem is that MEMACC should be done after regulator_set_voltage()
> when scaling up, and before regulator_set_voltage() when scaling down.
> 
> So even if MEMACC was a power domain, currently the OPP library does
> the _set_required_opps() call in the wrong order needed for MEMACC.
> 
> Like you said, the OPP library almost does everything already,
> so it probably makes most sense to extend it to your needs,
> rather than duplicating most of the code inside dev_pm_opp_set_rate().
> 
> 
> I guess what you really want is two new optional callbacks in
> dev_pm_opp_set_rate(), one before _generic_set_opp_regulator() and one
> after, where you could do the MEMACC thing.
> 
> The callbacks need to have a parameter that tells if we are scaling down
> or up.
> 
> Or, if Viresh doesn't like new function pointers, create a new
> OPP_EVENT_* that you can register for, and in that callback you do what
> you need.
> 
> Or, maybe you can even use the existing CPUFREQ_TRANSITION_NOTIFIER,
> with CPUFREQ_PRECHANGE / CPUFREQ_POSTCHANGE, however, I'm not sure
> how nicely they play when you are using the OPP library.
> 

I'm not sure. Overall all of this doesn't really sound like it is going
to make all this easier to understand (from looking at the device tree).
We then have required-opps for VDD_MX, and CPR (which isn't really a
power domain), and something entirely different for MEMACC (which like
CPR, isn't really a power domain).

I don't know, right now this mixture of different approaches sounds
rather complicated (and confusing) to me...

Just to throw another idea in the room: there seems to be a set_opp()
callback already in the OPP table, which bypasses the code that
updates clock and regulators (see ti-opp-supply.c). Actually if I'm
reading this correctly ti-opp-supply seems to implement adaptive voltage
scaling similar to CPR with it. Seemingly we have two different solutions
for the same concept now:

  - CPR implements a power domain provider (even though it's not really
    a power domain since it has only one consumer)
  - ti-opp-supply implements this with the set_opp() callback

In general I think this looks pretty nice - we don't duplicate the full
cpufreq driver, but have control about the order
regulators/clocks/power domains etc are changed.

I think something like this would fit quite well for my case
(scaling MX, APC and MEMACC without CPR). However, not sure how it would
integrate with the existing CPR driver at some point.

Adding Viresh to Cc in case he has some opinion for all this.

Thanks,
Stephan

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps
  2020-05-27 12:04                         ` Stephan Gerhold
@ 2020-05-27 12:59                           ` Niklas Cassel
  2020-05-27 20:56                             ` Stephan Gerhold
  2020-05-28  4:44                           ` Viresh Kumar
  1 sibling, 1 reply; 32+ messages in thread
From: Niklas Cassel @ 2020-05-27 12:59 UTC (permalink / raw)
  To: Stephan Gerhold
  Cc: Bjorn Andersson, Loic Poulain, agross, linux-arm-msm, Viresh Kumar

On Wed, May 27, 2020 at 02:04:52PM +0200, Stephan Gerhold wrote:
> > I guess what you really want is two new optional callbacks in
> > dev_pm_opp_set_rate(), one before _generic_set_opp_regulator() and one
> > after, where you could do the MEMACC thing.
> > 
> > The callbacks need to have a parameter that tells if we are scaling down
> > or up.
> > 
> > Or, if Viresh doesn't like new function pointers, create a new
> > OPP_EVENT_* that you can register for, and in that callback you do what
> > you need.
> > 
> > Or, maybe you can even use the existing CPUFREQ_TRANSITION_NOTIFIER,
> > with CPUFREQ_PRECHANGE / CPUFREQ_POSTCHANGE, however, I'm not sure
> > how nicely they play when you are using the OPP library.
> > 
> 
> I'm not sure. Overall all of this doesn't really sound like it is going
> to make all this easier to understand (from looking at the device tree).
> We then have required-opps for VDD_MX, and CPR (which isn't really a
> power domain), and something entirely different for MEMACC (which like
> CPR, isn't really a power domain).
> 
> I don't know, right now this mixture of different approaches sounds
> rather complicated (and confusing) to me...

You are going to need performance states where it is needed,
e.g. for controlling MX (as it is a power domain).
For performance states, you using the required-opps DT property.

My 50 cents is just to not use it for something that is not
a power domain, e.g. MEMACC.

> 
> Just to throw another idea in the room: there seems to be a set_opp()
> callback already in the OPP table, which bypasses the code that
> updates clock and regulators (see ti-opp-supply.c). Actually if I'm
> reading this correctly ti-opp-supply seems to implement adaptive voltage
> scaling similar to CPR with it. Seemingly we have two different solutions
> for the same concept now:
> 
>   - CPR implements a power domain provider (even though it's not really
>     a power domain since it has only one consumer)
>   - ti-opp-supply implements this with the set_opp() callback

Yes, and there are more ways to implement AVS, see e.g.
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=25cb20a212a1f989385dfe23230817e69c62bee5

Which probably would have been a better fit for CPR,
if it were to be designed today.

> 
> In general I think this looks pretty nice - we don't duplicate the full
> cpufreq driver, but have control about the order
> regulators/clocks/power domains etc are changed.
> 
> I think something like this would fit quite well for my case
> (scaling MX, APC and MEMACC without CPR). However, not sure how it would
> integrate with the existing CPR driver at some point.

You care about how to do DVFS without AVS (CPR).

Why do you worry about how it will look when, if ever,
you transition to full AVS (CPR)?

If the CPR driver is not changed, which I doubt, you will simply change
the device tree to remove the cpu-supply regulator and move it into the
new CPR DT node.

Old device trees will still use your DVFS solution, new device
trees will use the CPR DT node and will use the AVS solution.


Kind regards,
Niklas

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps
  2020-05-23 12:08                   ` Stephan Gerhold
@ 2020-05-27 20:47                     ` Georgi Djakov
  0 siblings, 0 replies; 32+ messages in thread
From: Georgi Djakov @ 2020-05-27 20:47 UTC (permalink / raw)
  To: Stephan Gerhold, Bjorn Andersson
  Cc: Loic Poulain, agross, linux-arm-msm, Stephen Boyd

Hi Stephan,

On 23.05.20 15:08, Stephan Gerhold wrote:
> +Cc Stephen Boyd, Georgi Djakov
> 
> On Thu, May 21, 2020 at 09:18:14PM +0200, Stephan Gerhold wrote:
>> On Thu, May 07, 2020 at 12:46:08PM +0200, Stephan Gerhold wrote:
>>> On Wed, May 06, 2020 at 11:18:07PM +0200, Stephan Gerhold wrote:
>>>> Hi,
>>>>
>>>> On Sun, Apr 26, 2020 at 02:31:48PM +0200, Stephan Gerhold wrote:
>>>>> On Wed, Apr 22, 2020 at 09:55:06PM -0700, Bjorn Andersson wrote:
>>>>>> On Fri 03 Apr 11:00 PDT 2020, Stephan Gerhold wrote:
>>>>>>
>>>>>>> On Fri, Apr 03, 2020 at 12:09:25PM +0200, Stephan Gerhold wrote:
>>>>>>>> On Thu, Apr 02, 2020 at 06:31:19PM -0700, Bjorn Andersson wrote:
>>>>>>>>> On Thu 02 Apr 01:13 PDT 2020, Stephan Gerhold wrote:
>>>>>>>>>
>>>>>>>>>> Hi,
>>>>>>>>>>
>>>>>>>>>> On Wed, Apr 01, 2020 at 07:50:59PM +0200, Loic Poulain wrote:
>>>>>>>>>>> The highest cpu frequency opps have been dropped because CPR is not
>>>>>>>>>>> supported. However, we can simply specify operating voltage so that
>>>>>>>>>>> they match the max corner voltages for each freq. With that, we can
>>>>>>>>>>> support up to 1.36Ghz. Ideally, msm8916 CPR should be implemented to
>>>>>>>>>>> fine tune operating voltages and optimize power consumption.
>>>>>>>>>>
>>>>>>>>>> Thanks for the patch! I was wondering how to enable the higher CPU
>>>>>>>>>> frequencies for a while now...
>>>>>>>>>>
>>>>>>>>>> I was actually quite excited to see CPR being mainlined for QCS404.
>>>>>>>>>> If we are trying to add such a workaround (rather than CPR) for MSM8916
>>>>>>>>>> now, does that mean it's unlikely to see CPR working for MSM8916
>>>>>>>>>> anytime soon?
>>>>>>>>>>
>>>>>>>>>> AFAICT, there is a WIP branch from Niklas Cassel here:
>>>>>>>>>> https://git.linaro.org/people/nicolas.dechesne/niklas.cassel/kernel.git/log/?h=cpr-msm8916-mainline
>>>>>>>>>> but it hasn't been updated for a while. (Not sure if it was working
>>>>>>>>>> already...)
>>>>>>>>>>
>>>>>>>>>> Can someone explain what is missing to make CPR work for MSM8916?
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> CPR needs to control 3 things; VDD_APC, VDD_MX and MEMACC. On QCS404 it
>>>>>>>>> seems we don't have to adjust VDD_MX, so the code for this is missing
>>>>>>>>> from the driver.
>>>>>>>>>
>>>>>>>>> So, afaict, what's missing is that rpmpd.c needs to gain support for
>>>>>>>>> 8916, then the CPR driver needs to gain a cpr_acc_desc and compatible
>>>>>>>>> for 8916, it needs to reference the VDDMX power domain and before/after
>>>>>>>>> we're adjusting the corner of the CPR we need to adjust the MX according
>>>>>>>>> to the mapping specified in the downstream kernel (i.e.  1->4, 2->5 and
>>>>>>>>> 3->7).
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Unfortunately, the requirement that VDDMX (VDD_MEM I presume) must be
>>>>>>>>> higher than VDD_APC most likely needs to be taken into consideration for
>>>>>>>>> Loic's proposed static voltage scaling as well. Unless VDD_MEM is left
>>>>>>>>> in Turbo mode from the boot loader I think we need to take VDDMX to
>>>>>>>>> corner 7 for speeds 998MHz and above (i.e. where we pull VDD_APC to
>>>>>>>>> 1.35V).
>>>>>>>>>
>>>>>>>>
>>>>>>>> I see! I wonder how hard it would be to add MSM8916 to rpmpd,
>>>>>>>> looking at previous commits it's mainly setting up a few defines?
>>>>>>>>
>>>>>>>> If I understand it correctly, the OPPs from rpmpd could then be
>>>>>>>> referenced as "required-opps" in the CPU OPP table so that VDD_MX is
>>>>>>>> scaled together with the CPU frequency, and doesn't need to stay at
>>>>>>>> turbo mode (like in v3 from Loic) the whole time.
>>>>>>>>
>>>>>>>
>>>>>>> I have been thinking about this some more and I think I came up with
>>>>>>> some changes that make sense (but not entirely sure).
>>>>>>>
>>>>>>> Based on the available downstream sources I guessed the defines to add
>>>>>>> for MSM8916 to the rpmpd driver. Then I added the VDD_MX OPPs as
>>>>>>> "required-opps" to the CPU OPP table so it would vote for the appopriate
>>>>>>> corners (with the mapping you mentioned above).
>>>>>>>
>>>>>>
>>>>>> I was not aware it was possible to describe the dependency between the
>>>>>> CPU opp table and MX in this fashion. If that's the case then this looks
>>>>>> really good and it should be straight forward to add MSM8916 support to
>>>>>> the CPR driver as well.
>>>>>>
>>>>>
>>>>> Indeed!
>>>>>
>>>>>>> I haven't tested it yet, maybe I can get some feedback first if the code
>>>>>>> seems reasonable or if I'm missing something obvious? :)
>>>>>>>
>>>>>>
>>>>>> Have you tested this yet?
>>>>>>
>>>>>
>>>>> I just did. It does not fully work, yet:
>>>>>
>>>>> rpmpd_set_performance() is indeed called as necessary when switching the
>>>>> CPU frequency. When I set 200 MHz it sets corner 3, with 533 MHz corner 4
>>>>> and starting with 998 MHz corner 6. So far so good :)
>>>>>
>>>>> However, there is never actually anything sent to the RPM. :(
>>>>> It bails out in rpmpd_set_performance() before calling rpmpd_aggregate_corner():
>>>>>
>>>>> 	/* Always send updates for vfc and vfl */
>>>>> 	if (!pd->enabled && pd->key != KEY_FLOOR_CORNER &&
>>>>> 	    pd->key != KEY_FLOOR_LEVEL)
>>>>> 		goto out;
>>>>>
>>>>> Seems like we just try to set performance states, but never actually
>>>>> enable (rpmpd_power_on()) the power domain (pd->enabled == false).
>>>>>
>>>>> I'm not sure which of the components involved here should handle that.
>>>>> The OPP core when setting required OPPs, the genpd core etc.
>>>>>
>>>>> Any ideas?
>>>>>
>>>>> Thanks,
>>>>> Stephan
>>>>>
>>>>
>>>> For now I have added something to qcom-cpufreq-nvmem.c to power on/enable
>>>> the power domain (not really sure if it belongs there...):
>>>>
>>>> diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
>>>> index a1b8238872a2..ed352ead037e 100644
>>>> --- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
>>>> +++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
>>>> @@ -26,6 +26,7 @@
>>>>  #include <linux/platform_device.h>
>>>>  #include <linux/pm_domain.h>
>>>>  #include <linux/pm_opp.h>
>>>> +#include <linux/pm_runtime.h>
>>>>  #include <linux/slab.h>
>>>>  #include <linux/soc/qcom/smem.h>
>>>>  
>>>> @@ -370,10 +371,13 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
>>>>  		}
>>>>  
>>>>  		if (drv->data->genpd_names) {
>>>> +			struct device **pd_dev;
>>>> +			const char **name = drv->data->genpd_names;
>>>> +
>>>>  			drv->genpd_opp_tables[cpu] =
>>>>  				dev_pm_opp_attach_genpd(cpu_dev,
>>>>  							drv->data->genpd_names,
>>>> -							NULL);
>>>> +							&pd_dev);
>>>>  			if (IS_ERR(drv->genpd_opp_tables[cpu])) {
>>>>  				ret = PTR_ERR(drv->genpd_opp_tables[cpu]);
>>>>  				if (ret != -EPROBE_DEFER)
>>>> @@ -382,6 +386,12 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
>>>>  						ret);
>>>>  				goto free_genpd_opp;
>>>>  			}
>>>> +
>>>> +			while (*name) {
>>>> +				pm_runtime_get_sync(*pd_dev);
>>>> +				name++;
>>>> +				pd_dev++;
>>>> +			}
>>>>  		}
>>>>  	}
>>>>
>>>> I really wonder why this doesn't affect CPR (or does it?).
>>>> So far I was not able to find anything that would power on/enable
>>>> the "cpr" power domain either. But I don't have a qcs404 to verify.
>>>>  
>>>> As far as I can tell from the log, the corner votes are correctly sent
>>>> to the RPM now when the CPU frequency is changed.
>>>>
>>>> However...
>>>>
>>>>>>> Also: Is there a good way to validate these changes?
>>>>>>> I suppose I could check the genpd state but that wouldn't tell me if the
>>>>>>> corner was applied correctly. Maybe I can check the actual voltage
>>>>>>> through the SPMI interface, hm...
>>>>>>>
>>>>>>
>>>>>> Validating that S2 and VDD_MX changes appropriately in Linux would be a
>>>>>> pretty good test.
>>>>>>
>>>>
>>>> Unfortunately I was not able to see any change in the voltage of L3 yet.
>>>> On samsung-a5u, /sys/class/regulator/<l3 spmi regulator>/microvolts
>>>> permanently reports 1300000 uV, even after a few different corner votes.
>>>>
>>>> I'm not sure if:
>>>>
>>>>   - This is normal (maybe some other remoteproc has a higher vote?)
>>>>     - I tried to disable wcnss, venus and hexagon without difference
>>>>
>>>>   - I'm just missing something in the code
>>>>
>>>>   - This is some peculiarity of the RPM firmware on samsung-a5u.
>>>>     (Although that seems quite unlikely to me...)
>>>>
>>>> Any ideas? :/
>>>>
>>>
>>> I just tried the same on the downstream kernel for samsung-a5u.
>>> There the L3 voltage doesn't change either, it stays on 1300000 uV
>>> permanently. So more likely would be either "this is normal" or
>>> "This is some peculiarity of the RPM firmware on samsung-a5u".
>>>
>>> I don't have a DB410c available for testing, but I'm curious if it would
>>> work correctly there. So far I have been unable to find any obvious
>>> mistake in my changes.
>>>
>>> I'm attaching the full diff (including Loic's changes) in case someone
>>> wants to test this on the DB410c (or some other MSM8916 device).
>>> Basically you need to:
>>>
>>>   1. CONFIG_QCOM_RPMPD=y
>>>      CONFIG_ARM_QCOM_CPUFREQ_NVMEM=y
>>>   2. Run it and change CPU frequencies a bit
>>>      (either with an automatic CPU governor, or by setting speeds
>>>       manually with powersave/performance/userspace)
>>>   3. There should be "set performance state" messages in dmesg
>>>      for the VDD_MX corner votes
>>>   4. Identify the spmi l3 regulator using /sys/class/regulator/*/name
>>>   5. Check the reported voltage in /sys/class/regulator/.../microvolts
>>>
>>> For me it stays on 1300000 uV, permanently. :(
>>>
>>
>> I recently bought another device that does not have signature checks
>> enabled. For now I have tested with the original firmware there:
>>
>> With or without my changes it stays at 1287500 uV permanently.
>> At least this seems somewhat more realistic since this is the
>> "super turbo" voltage.
>>
>> I tried disabling various things in case they affect this somehow:
>> WCNSS in particular sets 1287500 uV for pm8916_l3.
>> But even with WCNSS disabled, even with the regulator constraints
>> removed for pm8916_l3 and all changes reverted - it keeps reporting
>> 1287500 uV through the SPMI interface, no matter which CPU frequency
>> is selected.
>>
>> This is even more confusing because l3 is still at nominal voltage
>> (1150000 uV) in the lk bootloader. (I ported a part of the mainline
>> spmi_regulator driver to lk so I can dump the voltages from there...)
>> Somehow it gets changed when Linux is booted. Very confusing.
>>
>> Unlike on my previous test device, testing on downstream was successful:
>>
>>   - CPU frequency 200MHz - 800MHz results into 1150000 uV
>>     reported as voltage for l3 through the SPMI interface (corner 4/5)
>>   - Higher CPU frequencies result into 1287500 uV (corner 7)
>>
>> Again I ported the spmi_regulator driver from mainline to downstream,
>> so the way the voltage is read should be the same.
>>
>> Clearly something must be different/missing in my changes,
>> but I still have no idea what exactly.
>> Any suggestions would be highly appreciated :)
>>
> 
> After several hours of debugging I finally figured out what's wrong:
> 
> I guess there are various dependencies on the VDD_CX/VDD_MX
> voltage rails in the RPM: VDD_MX will be always higher than VDD_CX,
> and VDD_CX is also influenced by some of the clocks.
> 
> If I disable the rpmcc/clk-smd-rpm entirely in the device tree,
> suddenly the VDD_MX voltage scales correctly with my changes.
> 
> This seems to happen because the clk-smd-rpm forces all clocks to
> maximum state in the clk_smd_rpm_handoff() function. In my case,
> the clocks used for interconnect cause VDD_CX to scale to "super turbo",
> which in turn keeps VDD_MX on "super turbo" as well.
> 
> I imagine this will be solved properly once we enable the interconnect
> driver and all the necessary consumers.
> 
> But in general, I think this "handoff" behavior clk-smd-rpm is a bit
> weird: As far as I understand, the clock framework normally disables
> unused clocks shortly after the boot is complete.
> 
> The clk-smd-rpm driver does the opposite: it forces all clocks to on,
> to maximum rate and does not seem to report that to the clock framework.
> If there is no consumer for the clock it seems to stay on and on maximum
> frequency forever.
> 
> For example, in order to avoid other remoteprocs influencing the
> VDD_CX/VDD_MX voting I have disabled all additional remoteprocs in the
> device tree (e.g. WCNSS, venus, ...)
> 
> Before Linux is booted (dumped from the PMIC registers in the lk
> bootloader), the rf_clk1/2 (modem/wcnss) is off. With clk-smd-rpm
> disabled it stays off too. However, when clk-smd-rpm is loaded that
> "handoff" function forces them on, and they're never turned off again.
> 
> This is invisible to the clock framework - according to the clock
> debugfs they are off. But reading the PMIC registers reveals they are on.
> 
> I suppose that behavior makes sense for the interconnect clocks,
> disabling those without an interconnect driver wouldn't do much good.
> But for the other clocks that doesn't seem quite right to me.
> 
> What do you think?

I agree with you. Sending a clock frequency request from Linux side to
the RPM processor would mean that the RPM will maintain the voltage
needed for this frequency.
We should not "handoff" all RPM clocks, but just the interconnect clocks
(snoc, pnoc, bimc). Then, if there is an interconnect driver enabled for
the platform, it will take care of scaling these. But from Linux side,
we should not touch the other RPM clocks related to wifi, modem etc.

Thanks,
Georgi

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps
  2020-05-27 12:59                           ` Niklas Cassel
@ 2020-05-27 20:56                             ` Stephan Gerhold
  2020-05-27 23:10                               ` Niklas Cassel
  0 siblings, 1 reply; 32+ messages in thread
From: Stephan Gerhold @ 2020-05-27 20:56 UTC (permalink / raw)
  To: Niklas Cassel
  Cc: Bjorn Andersson, Loic Poulain, agross, linux-arm-msm, Viresh Kumar

On Wed, May 27, 2020 at 02:59:19PM +0200, Niklas Cassel wrote:
> On Wed, May 27, 2020 at 02:04:52PM +0200, Stephan Gerhold wrote:
> > > I guess what you really want is two new optional callbacks in
> > > dev_pm_opp_set_rate(), one before _generic_set_opp_regulator() and one
> > > after, where you could do the MEMACC thing.
> > > 
> > > The callbacks need to have a parameter that tells if we are scaling down
> > > or up.
> > > 
> > > Or, if Viresh doesn't like new function pointers, create a new
> > > OPP_EVENT_* that you can register for, and in that callback you do what
> > > you need.
> > > 
> > > Or, maybe you can even use the existing CPUFREQ_TRANSITION_NOTIFIER,
> > > with CPUFREQ_PRECHANGE / CPUFREQ_POSTCHANGE, however, I'm not sure
> > > how nicely they play when you are using the OPP library.
> > > 
> > 
> > I'm not sure. Overall all of this doesn't really sound like it is going
> > to make all this easier to understand (from looking at the device tree).
> > We then have required-opps for VDD_MX, and CPR (which isn't really a
> > power domain), and something entirely different for MEMACC (which like
> > CPR, isn't really a power domain).
> > 
> > I don't know, right now this mixture of different approaches sounds
> > rather complicated (and confusing) to me...
> 
> You are going to need performance states where it is needed,
> e.g. for controlling MX (as it is a power domain).
> For performance states, you using the required-opps DT property.
> 
> My 50 cents is just to not use it for something that is not
> a power domain, e.g. MEMACC.
> 

I agree.

> > 
> > Just to throw another idea in the room: there seems to be a set_opp()
> > callback already in the OPP table, which bypasses the code that
> > updates clock and regulators (see ti-opp-supply.c). Actually if I'm
> > reading this correctly ti-opp-supply seems to implement adaptive voltage
> > scaling similar to CPR with it. Seemingly we have two different solutions
> > for the same concept now:
> > 
> >   - CPR implements a power domain provider (even though it's not really
> >     a power domain since it has only one consumer)
> >   - ti-opp-supply implements this with the set_opp() callback
> 
> Yes, and there are more ways to implement AVS, see e.g.
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=25cb20a212a1f989385dfe23230817e69c62bee5
> 
> Which probably would have been a better fit for CPR,
> if it were to be designed today.
> 

Would this actually work if you update the voltage of the current OPP?
Looking at the qcom-cpr code the voltage is dynamically changed when
receiving IRQs. I would say with that function you can only change the
voltage when switching to that OPP the next time. Maybe I'm wrong though.

Otherwise that's pretty nice, because the setup is very similar with or
without CPR (since the regulator is still managed by the OPP core).

> > 
> > In general I think this looks pretty nice - we don't duplicate the full
> > cpufreq driver, but have control about the order
> > regulators/clocks/power domains etc are changed.
> > 
> > I think something like this would fit quite well for my case
> > (scaling MX, APC and MEMACC without CPR). However, not sure how it would
> > integrate with the existing CPR driver at some point.
> 
> You care about how to do DVFS without AVS (CPR).
> 
> Why do you worry about how it will look when, if ever,
> you transition to full AVS (CPR)?
> 

I mean, CPR is arguably the better solution on long term.
I doubt it will be me who will enable it for MSM8916 (mainly for lack of
understanding of the whole scaling formulas etc), but IMO it would be
worth to at least consider how to switch in the future.

> If the CPR driver is not changed, which I doubt, you will simply change
> the device tree to remove the cpu-supply regulator and move it into the
> new CPR DT node.
> 
> Old device trees will still use your DVFS solution, new device
> trees will use the CPR DT node and will use the AVS solution.
> 

I think my concern is essentially that I would duplicate the MEMACC code
into a new driver utilizing .set_opp() - and to keep backwards
compatibility we would need to keep that duplication forever.

The MEMACC scaling isn't all that complicated, but overall I would
prefer to avoid introducing duplication in the first place.

Also: If full CPR ever happens we would be basically back
to one part of the current discussion: specifying two "required-opps"
MX and CPR (= APC + MEMACC) would result in the wrong order
when scaling up/down.

But maybe I just worry too much?

Thanks,
Stephan

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps
  2020-05-27 20:56                             ` Stephan Gerhold
@ 2020-05-27 23:10                               ` Niklas Cassel
  2020-05-28 13:32                                 ` Stephan Gerhold
  0 siblings, 1 reply; 32+ messages in thread
From: Niklas Cassel @ 2020-05-27 23:10 UTC (permalink / raw)
  To: Stephan Gerhold
  Cc: Bjorn Andersson, Loic Poulain, agross, linux-arm-msm, Viresh Kumar

On Wed, May 27, 2020 at 10:56:07PM +0200, Stephan Gerhold wrote:
> > If the CPR driver is not changed, which I doubt, you will simply change
> > the device tree to remove the cpu-supply regulator and move it into the
> > new CPR DT node.
> > 
> > Old device trees will still use your DVFS solution, new device
> > trees will use the CPR DT node and will use the AVS solution.
> > 
> 
> I think my concern is essentially that I would duplicate the MEMACC code
> into a new driver utilizing .set_opp() - and to keep backwards
> compatibility we would need to keep that duplication forever.

The cleanest solution is probably to create a new memacc platform device
driver, and make the new code use that, and refactor CPR to use the same.

> 
> The MEMACC scaling isn't all that complicated, but overall I would
> prefer to avoid introducing duplication in the first place.
> 
> Also: If full CPR ever happens we would be basically back
> to one part of the current discussion: specifying two "required-opps"
> MX and CPR (= APC + MEMACC) would result in the wrong order
> when scaling up/down.
> 
> But maybe I just worry too much?

I guess that whoever implements CPR on msm8916 will either call
dev_pm_genpd_set_performance_state() on MX directly from cpr_scale_voltage()
or perhaps change OPP core so that it runs the required-opps in reverse
order when scaling down, like you previously suggested.

Please don't take my suggestions as the only way forward though.
Hopefully I provided more clarity than confusion.
Will step back so that someone else has a chance to chime in :)


Kind regards,
Niklas

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps
  2020-05-27 12:04                         ` Stephan Gerhold
  2020-05-27 12:59                           ` Niklas Cassel
@ 2020-05-28  4:44                           ` Viresh Kumar
  1 sibling, 0 replies; 32+ messages in thread
From: Viresh Kumar @ 2020-05-28  4:44 UTC (permalink / raw)
  To: Stephan Gerhold
  Cc: Niklas Cassel, Bjorn Andersson, Loic Poulain, agross,
	linux-arm-msm, Viresh Kumar

On 27-05-20, 14:04, Stephan Gerhold wrote:
> +Cc Viresh (should have already done this earlier :) )
> 
> On Wed, May 27, 2020 at 12:39:21PM +0200, Niklas Cassel wrote:
> > On Tue, May 26, 2020 at 10:54:03PM +0200, Stephan Gerhold wrote:
> > > Speaking of the current solution, I also have to say that (IMO) the
> > > device tree binding for "required-opps" is rather confusing
> > > and potentially misleading.
> > > 
> > > e.g. for VDD_MX scaling I use
> > > 
> > > 	required-opps = <&rpmpd_opp_nom>;
> > > 
> > > but looking at just the OPP table absolutely nothing tells me this is
> > > supposed to apply to VDD_MX. You actually need to go search for the cpu@
> > > device tree node and then know that some of the power domains there
> > > (in some order) are eventually going to be used for the required-opps
> > > there. The order is only defined by the qcom-nvmem-cpufreq driver.
> > > 
> > > It took me a few hours to get that right... :)

I agree, we need a way to figure out devices as well for which the
required-opp works. And yes that's missing.

> > > Nevertheless I guess we need a solution for scaling MEMACC without CPR
> > > for now. :) I'm not sure if rewriting all this is very realistic
> > > (if even possible). So I guess we might be stuck with the genpd approach?
> > 
> > I agree, the CPR driver will most likely not be changed now, since we
> > need to be compatible with the existing device tree.

A driver can be changed as much as you want, just that you need to
honor both new and old DTs.

> > 
> > For DVFS without CPR:
> > 
> > You need to scale APC, MX, MEMACC.
> > 
> > If we don't care about MEMACC, then the existing code in the OPP library
> > satisfies all our needs.
> > The problem here is if we need to do MEMACC as well.
> > 
> > I don't think it is proper to implement MEMACC as a power domain
> > (because it is not). Thus, we can't add it as a required-opp.

Required-opps can be extended if there is a real need. It isn't just
about power domains.

> > Another problem is that MEMACC should be done after regulator_set_voltage()
> > when scaling up, and before regulator_set_voltage() when scaling down.
> > 
> > So even if MEMACC was a power domain, currently the OPP library does
> > the _set_required_opps() call in the wrong order needed for MEMACC.
> > 
> > Like you said, the OPP library almost does everything already,
> > so it probably makes most sense to extend it to your needs,
> > rather than duplicating most of the code inside dev_pm_opp_set_rate().
> > 
> > 
> > I guess what you really want is two new optional callbacks in
> > dev_pm_opp_set_rate(), one before _generic_set_opp_regulator() and one
> > after, where you could do the MEMACC thing.
> > 
> > The callbacks need to have a parameter that tells if we are scaling down
> > or up.

NAK :)

> > Or, if Viresh doesn't like new function pointers, create a new
> > OPP_EVENT_* that you can register for, and in that callback you do what
> > you need.

NAK :)

> > Or, maybe you can even use the existing CPUFREQ_TRANSITION_NOTIFIER,
> > with CPUFREQ_PRECHANGE / CPUFREQ_POSTCHANGE, however, I'm not sure
> > how nicely they play when you are using the OPP library.
> > 
> 
> I'm not sure. Overall all of this doesn't really sound like it is going
> to make all this easier to understand (from looking at the device tree).
> We then have required-opps for VDD_MX, and CPR (which isn't really a
> power domain), and something entirely different for MEMACC (which like
> CPR, isn't really a power domain).
> 
> I don't know, right now this mixture of different approaches sounds
> rather complicated (and confusing) to me...
> 
> Just to throw another idea in the room: there seems to be a set_opp()
> callback already in the OPP table, which bypasses the code that
> updates clock and regulators (see ti-opp-supply.c). Actually if I'm
> reading this correctly ti-opp-supply seems to implement adaptive voltage
> scaling similar to CPR with it. Seemingly we have two different solutions
> for the same concept now:
> 
>   - CPR implements a power domain provider (even though it's not really
>     a power domain since it has only one consumer)
>   - ti-opp-supply implements this with the set_opp() callback
> 
> In general I think this looks pretty nice - we don't duplicate the full
> cpufreq driver, but have control about the order
> regulators/clocks/power domains etc are changed.
> 
> I think something like this would fit quite well for my case
> (scaling MX, APC and MEMACC without CPR). However, not sure how it would
> integrate with the existing CPR driver at some point.
> 
> Adding Viresh to Cc in case he has some opinion for all this.

OPP core broadly is a place where we store/parse some data from the DT
and keep, so others can use it. opp_set_rate() was added to it to
avoid duplicating the same thing across drivers. As you have figured
out, the right way for you to solve it is by using your set_opp()
callback along with required-opps thing.

-- 
viresh

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps
  2020-05-27 23:10                               ` Niklas Cassel
@ 2020-05-28 13:32                                 ` Stephan Gerhold
  0 siblings, 0 replies; 32+ messages in thread
From: Stephan Gerhold @ 2020-05-28 13:32 UTC (permalink / raw)
  To: Niklas Cassel
  Cc: Bjorn Andersson, Loic Poulain, agross, linux-arm-msm, Viresh Kumar

On Thu, May 28, 2020 at 01:10:25AM +0200, Niklas Cassel wrote:
> On Wed, May 27, 2020 at 10:56:07PM +0200, Stephan Gerhold wrote:
> > > If the CPR driver is not changed, which I doubt, you will simply change
> > > the device tree to remove the cpu-supply regulator and move it into the
> > > new CPR DT node.
> > > 
> > > Old device trees will still use your DVFS solution, new device
> > > trees will use the CPR DT node and will use the AVS solution.
> > > 
> > 
> > I think my concern is essentially that I would duplicate the MEMACC code
> > into a new driver utilizing .set_opp() - and to keep backwards
> > compatibility we would need to keep that duplication forever.
> 
> The cleanest solution is probably to create a new memacc platform device
> driver, and make the new code use that, and refactor CPR to use the same.
> 

I will try to come up with something like that, thank you!

> > 
> > The MEMACC scaling isn't all that complicated, but overall I would
> > prefer to avoid introducing duplication in the first place.
> > 
> > Also: If full CPR ever happens we would be basically back
> > to one part of the current discussion: specifying two "required-opps"
> > MX and CPR (= APC + MEMACC) would result in the wrong order
> > when scaling up/down.
> > 
> > But maybe I just worry too much?
> 
> I guess that whoever implements CPR on msm8916 will either call
> dev_pm_genpd_set_performance_state() on MX directly from cpr_scale_voltage()
> or perhaps change OPP core so that it runs the required-opps in reverse
> order when scaling down, like you previously suggested.
> 
> Please don't take my suggestions as the only way forward though.
> Hopefully I provided more clarity than confusion.
> Will step back so that someone else has a chance to chime in :)

I'm a bit confused at the moment, but it's mainly because we discussed
so many different options. I will need some time to properly look
at all of them and come up with a potential solution.

Thanks for taking the time to answer all my questions! :)
Stephan

^ permalink raw reply	[flat|nested] 32+ messages in thread

end of thread, back to index

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-04-01 17:50 [PATCH] arch: arm64: dts: apq8016-dbc: Add missing cpu opps Loic Poulain
2020-04-01 23:46 ` Bjorn Andersson
2020-04-02  8:13 ` Stephan Gerhold
2020-04-02  9:58   ` Loic Poulain
2020-04-03  1:31   ` Bjorn Andersson
2020-04-03 10:09     ` Stephan Gerhold
2020-04-03 18:00       ` Stephan Gerhold
2020-04-23  4:55         ` Bjorn Andersson
2020-04-26 12:31           ` Stephan Gerhold
2020-05-06 21:18             ` Stephan Gerhold
2020-05-07  5:34               ` Bjorn Andersson
2020-05-08 12:08                 ` Ulf Hansson
2020-05-08 13:42                   ` Stephan Gerhold
2020-05-11  5:29                   ` Viresh Kumar
2020-05-07 10:46               ` Stephan Gerhold
2020-05-21 19:18                 ` Stephan Gerhold
2020-05-23 12:08                   ` Stephan Gerhold
2020-05-27 20:47                     ` Georgi Djakov
2020-05-25 15:32           ` Niklas Cassel
2020-05-25 16:36             ` Stephan Gerhold
2020-05-25 19:44               ` Niklas Cassel
2020-05-26  8:59                 ` Stephan Gerhold
2020-05-26 15:54                   ` Niklas Cassel
2020-05-26 20:54                     ` Stephan Gerhold
2020-05-27 10:39                       ` Niklas Cassel
2020-05-27 12:04                         ` Stephan Gerhold
2020-05-27 12:59                           ` Niklas Cassel
2020-05-27 20:56                             ` Stephan Gerhold
2020-05-27 23:10                               ` Niklas Cassel
2020-05-28 13:32                                 ` Stephan Gerhold
2020-05-28  4:44                           ` Viresh Kumar
2020-04-28 20:04 ` Amit Kucheria

Linux-ARM-MSM Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-arm-msm/0 linux-arm-msm/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-arm-msm linux-arm-msm/ https://lore.kernel.org/linux-arm-msm \
		linux-arm-msm@vger.kernel.org
	public-inbox-index linux-arm-msm

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-arm-msm


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git