Skip to contentSkip to conversation

Add power domain driver for corners on msm8996/sdm845

PATCH Superseded Rajendra Nayak 3 participants 16 messages Dec 12, 2018 – Dec 17, 2018

Subsystems (9)

v7 of 11 Superseded Latest is v11 →

lore
Share & tools
lore
#0 lore raw

v7 cover Add power domain driver for corners on msm8996/sdm845

Changes in v7:
* Rebased on Andy's for-next, and used the updated cmd_db_read_aux_data()
* Other minor fixes, all in 'PATCH 06/10' as suggested by Stephen

Changes in v6:
* OPP binding updates for qcom,level reviewed by Rob
* DT bindings for rpmpd and rpmhpd updated to specify the OPP tables as child nodes of the power-controller itself
* Removed some module specific remains from the drivers, now that they can only be built-in
* Added a simple_opp_to_performance_state() helper

Changes in v5:
* First 6 patches are unchanged
* Patch 7/8 adds the DT node for rpmh power-controller on sdm845 and the corresponding OPP tables for it to describe the performance states
* Patch 8/8 adds a parent/child relationship across mx/cx and mx_ao/cx_ao as needed on sdm845 platform. This patch is dependent on the series from Viresh [1] which adds support to propogate performance states across the power domain hierarchy which is still being reviewed

Changes in v4:
* Included the patch to add qcom-opp bindings (dropped accidentally in v3)
* merged the patches to add bindings for rpm and rpmh, added consumer binding example
* Made the drivers built in, removed .remove
* Added better description in changelog for PATCH 6/6
* Updated rpmhpd_aggregate_corner() based on Davids feedback
* rpmhpd_set_performance_state() returns max corner, in cases where its called with an INT_MAX
* Dropped the patch to max vote on all corners at init, the patch did not work anyway, and it shouldn't be needed now

Changes in v3:
* Bindings split into seperate patches
* Bindings updated to remove duplicate OPP table phandles
* DT headers defining macros for Power domain indexes and OPP levels
* Optimisations to use rpmh_write_async() whereever applicable
* Fixed up handling of ACTIVE_ONLY/WAKE_ONLY/SLEEP voting for RPMh
* Fixed the vlvl to hlvl conversions in set_performance
* Other minor fixes based on review of v2
* TODO: This series does not handle the case where all VDD_MX votes should be higher than VDD_CX from APPs, as pointed out
by David Collins in v2. This needs support at genpd to propogate performance state up the parents, if we model these as Parent/Child to handle the interdependency.

Changes in v2:
* added a power domain driver for sdm845 which supports communicating to RPMh
* dropped the changes to sdhc driver to move over to using OPP
as there is active discussion on using OPP as the interface vs handling all of it in clock drivers
* Other minor binding updates based on review of v1

With performance state support for genpd/OPP merged, this is an effort to model a power domain driver to communicate corner/level values for qualcomm platforms to RPM (Remote Power Manager) and RPMh.

[1] https://lkml.org/lkml/2018/11/26/333

Rajendra Nayak (10):
dt-bindings: opp: Introduce qcom-opp bindings
dt-bindings: power: Add qcom rpm power domain driver bindings
soc: qcom: rpmpd: Add a Power domain driver to model corners
soc: qcom: rpmpd: Add support for get/set performance state
arm64: dts: msm8996: Add rpmpd device node
soc: qcom: rpmhpd: Add RPMh power domain driver
arm64: dts: sdm845: Add rpmh powercontroller node
PM / Domains: Add a simple_opp_to_performance_state() helper
soc: qcom: rpmpd: Use simple_opp_to_performance_state() helper
soc: qcom: rpmhpd: Mark mx as a parent for cx

 .../devicetree/bindings/opp/qcom-opp.txt      |  25 ++
 .../devicetree/bindings/power/qcom,rpmpd.txt  | 146 +++++++
 arch/arm64/boot/dts/qcom/msm8996.dtsi         |  34 ++
 arch/arm64/boot/dts/qcom/sdm845.dtsi          |  51 +++
 drivers/base/power/domain.c                   |  17 +
 drivers/soc/qcom/Kconfig                      |  18 +
 drivers/soc/qcom/Makefile                     |   2 +
 drivers/soc/qcom/rpmhpd.c                     | 402 ++++++++++++++++++
 drivers/soc/qcom/rpmpd.c                      | 317 ++++++++++++++
 include/dt-bindings/power/qcom-rpmpd.h        |  39 ++
 include/linux/pm_domain.h                     |   9 +
 11 files changed, 1060 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/opp/qcom-opp.txt
 create mode 100644 Documentation/devicetree/bindings/power/qcom,rpmpd.txt
 create mode 100644 drivers/soc/qcom/rpmhpd.c
 create mode 100644 drivers/soc/qcom/rpmpd.c
 create mode 100644 include/dt-bindings/power/qcom-rpmpd.h
Signature · 2 lines
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
#1 lore raw

PATCH v7 1/10 dt-bindings: opp: Introduce qcom-opp bindings

On Qualcomm Technologies, Inc. platforms, an OPP node needs to describe an additional level/corner value that is then communicated to a remote microprocessor by the CPU, which then takes some actions (like adjusting voltage values across various rails) based on the value passed.

Describe these bindings in the qcom-opp bindings document.

---
 .../devicetree/bindings/opp/qcom-opp.txt      | 25 +++++++++++++++++++
 1 file changed, 25 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/opp/qcom-opp.txt
Documentation/devicetree/bindings/opp/qcom-opp.txt new file +25 -0
new file mode 100644
index 000000000000..db4d970c7ec7
@@ -0,0 +1,25 @@
+Qualcomm OPP bindings to descibe OPP nodes with corner/level values
+
+OPP tables for devices on Qualcomm platforms require an additional
+platform specific corner/level value to be specified.
+This value is passed on to the RPM (Resource Power Manager) by
+the CPU, which then takes the necessary actions to set a voltage
+rail to an appropriate voltage based on the value passed.
+
+The bindings are based on top of the operating-points-v2 bindings
+described in Documentation/devicetree/bindings/opp/opp.txt
+Additional properties are described below.
+
+* OPP Table Node
+
+Required properties:
+- compatible: Allow OPPs to express their compatibility. It should be:
+  "operating-points-v2-qcom-level"
+
+* OPP Node
+
+Required properties:
+- qcom,level: On Qualcomm platforms an OPP node can describe a positive value
+representing a corner/level that's communicated with a remote microprocessor
+(usually called the RPM) which then translates it into a certain voltage on
+a voltage rail.
Signature · 2 lines
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
#2 lore raw

PATCH v7 2/10 dt-bindings: power: Add qcom rpm power domain driver bindings

In reply to Rajendra Nayak

Add DT bindings to describe the rpm/rpmh power domains found on Qualcomm Technologies, Inc. SoCs. These power domains communicate a performance state to RPM/RPMh, which then translates it into corresponding voltage on a PMIC rail.

---
 .../devicetree/bindings/power/qcom,rpmpd.txt  | 146 ++++++++++++++++++
 include/dt-bindings/power/qcom-rpmpd.h        |  39 +++++
 2 files changed, 185 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/power/qcom,rpmpd.txt
 create mode 100644 include/dt-bindings/power/qcom-rpmpd.h
Documentation/devicetree/bindings/power/qcom,rpmpd.txt new file +146 -0
new file mode 100644
index 000000000000..a776e4407f09
@@ -0,0 +1,146 @@
+Qualcomm RPM/RPMh Power domains
+
+For RPM/RPMh Power domains, we communicate a performance state to RPM/RPMh
+which then translates it into a corresponding voltage on a rail
+
+Required Properties:
+ - compatible: Should be one of the following
+	* qcom,msm8996-rpmpd: RPM Power domain for the msm8996 family of SoC
+	* qcom,sdm845-rpmhpd: RPMh Power domain for the sdm845 family of SoC
+ - power-domain-cells: number of cells in Power domain specifier
+	must be 1.
+ - operating-points-v2: Phandle to the OPP table for the Power domain.
+	Refer to Documentation/devicetree/bindings/power/power_domain.txt
+	and Documentation/devicetree/bindings/opp/qcom-opp.txt for more details
+
+Refer to <dt-bindings/power/qcom-rpmpd.h> for the level values for
+various OPPs for different platforms as well as Power domain indexes
+
+Example: rpmh power domain controller and OPP table
+
+#include <dt-bindings/power/qcom-rpmhpd.h>
+
+qcom,level values specified in the OPP tables for RPMh power domains
+should use the RPMH_REGULATOR_LEVEL_* constants from
+<dt-bindings/power/qcom-rpmhpd.h>
+
+	rpmhpd: power-controller {
+		compatible = "qcom,sdm845-rpmhpd";
+		#power-domain-cells = <1>;
+		operating-points-v2 = <&rpmhpd_opp_table>;
+
+		rpmhpd_opp_table: opp-table {
+			compatible = "operating-points-v2-qcom-level";
+
+			rpmhpd_opp_ret: opp1 {
+				qcom,level = <RPMH_REGULATOR_LEVEL_RETENTION>;
+			};
+
+			rpmhpd_opp_min_svs: opp2 {
+				qcom,level = <RPMH_REGULATOR_LEVEL_MIN_SVS>;
+			};
+
+			rpmhpd_opp_low_svs: opp3 {
+				qcom,level = <RPMH_REGULATOR_LEVEL_LOW_SVS>;
+			};
+
+			rpmhpd_opp_svs: opp4 {
+				qcom,level = <RPMH_REGULATOR_LEVEL_SVS>;
+			};
+
+			rpmhpd_opp_svs_l1: opp5 {
+				qcom,level = <RPMH_REGULATOR_LEVEL_SVS_L1>;
+			};
+
+			rpmhpd_opp_nom: opp6 {
+				qcom,level = <RPMH_REGULATOR_LEVEL_NOM>;
+			};
+
+			rpmhpd_opp_nom_l1: opp7 {
+				qcom,level = <RPMH_REGULATOR_LEVEL_NOM_L1>;
+			};
+
+			rpmhpd_opp_nom_l2: opp8 {
+				qcom,level = <RPMH_REGULATOR_LEVEL_NOM_L2>;
+			};
+
+			rpmhpd_opp_turbo: opp9 {
+				qcom,level = <RPMH_REGULATOR_LEVEL_TURBO>;
+			};
+
+			rpmhpd_opp_turbo_l1: opp10 {
+				qcom,level = <RPMH_REGULATOR_LEVEL_TURBO_L1>;
+			};
+		};
+	};
+
+Example: rpm power domain controller and OPP table
+
+	rpmpd: power-controller {
+		compatible = "qcom,msm8996-rpmpd";
+		#power-domain-cells = <1>;
+		operating-points-v2 = <&rpmpd_opp_table>;
+
+		rpmpd_opp_table: opp-table {
+			compatible = "operating-points-v2-qcom-level";
+
+			rpmpd_opp_low: opp1 {
+				qcom,level = <1>;
+			};
+
+			rpmpd_opp_ret: opp2 {
+				qcom,level = <2>;
+			};
+
+			rpmpd_opp_svs: opp3 {
+				qcom,level = <3>;
+			};
+
+			rpmpd_opp_normal: opp4 {
+				qcom,level = <4>;
+			};
+
+			rpmpd_opp_high: opp5 {
+				qcom,level = <5>;
+			};
+
+			rpmpd_opp_turbo: opp6 {
+				qcom,level = <6>;
+			};
+		};
+	};
+
+Example: Client/Consumer device using OPP table
+
+	leaky-device0@12350000 {
+		compatible = "foo,i-leak-current";
+		reg = <0x12350000 0x1000>;
+		power-domains = <&rpmhpd SDM845_MX>;
+		operating-points-v2 = <&leaky_opp_table>;
+	};
+
+
+	leaky_opp_table: opp-table {
+		compatible = "operating-points-v2";
+
+		opp1 {
+			opp-hz = /bits/ 64 <144000>;
+			required-opps = <&rpmhpd_opp_low>;
+		};
+
+		opp2 {
+			opp-hz = /bits/ 64 <400000>;
+			required-opps = <&rpmhpd_opp_ret>;
+		};
+
+		opp3 {
+			opp-hz = /bits/ 64 <20000000>;
+			required-opps = <&rpmpd_opp_svs>;
+		};
+
+		opp4 {
+			opp-hz = /bits/ 64 <25000000>;
+			required-opps = <&rpmpd_opp_normal>;
+		};
+
+	};
include/dt-bindings/power/qcom-rpmpd.h new file +39 -0
new file mode 100644
index 000000000000..87d9c6611682
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved. */
+
+#ifndef _DT_BINDINGS_POWER_QCOM_RPMPD_H
+#define _DT_BINDINGS_POWER_QCOM_RPMPD_H
+
+/* SDM845 Power Domain Indexes */
+#define SDM845_EBI	0
+#define SDM845_MX	1
+#define SDM845_MX_AO	2
+#define SDM845_CX	3
+#define SDM845_CX_AO	4
+#define SDM845_LMX	5
+#define SDM845_LCX	6
+#define SDM845_GFX	7
+#define SDM845_MSS	8
+
+/* SDM845 Power Domain performance levels */
+#define RPMH_REGULATOR_LEVEL_RETENTION	16
+#define RPMH_REGULATOR_LEVEL_MIN_SVS	48
+#define RPMH_REGULATOR_LEVEL_LOW_SVS	64
+#define RPMH_REGULATOR_LEVEL_SVS	128
+#define RPMH_REGULATOR_LEVEL_SVS_L1	192
+#define RPMH_REGULATOR_LEVEL_NOM	256
+#define RPMH_REGULATOR_LEVEL_NOM_L1	320
+#define RPMH_REGULATOR_LEVEL_NOM_L2	336
+#define RPMH_REGULATOR_LEVEL_TURBO	384
+#define RPMH_REGULATOR_LEVEL_TURBO_L1	416
+
+/* MSM8996 Power Domain Indexes */
+#define MSM8996_VDDCX		0
+#define MSM8996_VDDCX_AO	1
+#define MSM8996_VDDCX_VFC	2
+#define MSM8996_VDDMX		3
+#define MSM8996_VDDMX_AO	4
+#define MSM8996_VDDSSCX		5
+#define MSM8996_VDDSSCX_VFC	6
+
+#endif
Signature · 2 lines
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
maintainer Reviewed-by on v7 2/10
#3 lore raw

Re: [PATCH v7 02/10] dt-bindings: power: Add qcom rpm power domain driver bindings

Quoted 23 lines · Rajendra Nayak

Add DT bindings to describe the rpm/rpmh power domains found on Qualcomm Technologies, Inc. SoCs. These power domains communicate a performance state to RPM/RPMh, which then translates it into corresponding voltage on a PMIC rail.

---
 .../devicetree/bindings/power/qcom,rpmpd.txt  | 146 ++++++++++++++++++
 include/dt-bindings/power/qcom-rpmpd.h        |  39 +++++
 2 files changed, 185 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/power/qcom,rpmpd.txt
 create mode 100644 include/dt-bindings/power/qcom-rpmpd.h
Documentation/devicetree/bindings/power/qcom,rpmpd.txt new file +1 -0
new file mode 100644
index 000000000000..a776e4407f09
@@ -0,0 +1,146 @@
+Qualcomm RPM/RPMh Power domains

Documentation/devicetree/bindings/power/qcom,rpmpd.txt line 11

Quoted 10 lines
Documentation/devicetree/bindings/power/qcom,rpmpd.txt new file +10 -0
+
+For RPM/RPMh Power domains, we communicate a performance state to RPM/RPMh
+which then translates it into a corresponding voltage on a rail
+
+Required Properties:
+ - compatible: Should be one of the following
+	* qcom,msm8996-rpmpd: RPM Power domain for the msm8996 family of SoC
+	* qcom,sdm845-rpmhpd: RPMh Power domain for the sdm845 family of SoC
+ - power-domain-cells: number of cells in Power domain specifier
+	must be 1.

#power-domain-cells

With that,

#4 lore raw

PATCH v7 3/10 soc: qcom: rpmpd: Add a Power domain driver to model corners

In reply to Rajendra Nayak

The Power domains for corners just pass the performance state set by the consumers to the RPM (Remote Power manager) which then takes care of setting the appropriate voltage on the corresponding rails to meet the performance needs.

We add all power domain data needed on msm8996 here. This driver can easily be extended by adding data for other qualcomm SoCs as well.

---
 drivers/soc/qcom/Kconfig  |   9 ++
 drivers/soc/qcom/Makefile |   1 +
 drivers/soc/qcom/rpmpd.c  | 282 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 292 insertions(+)
 create mode 100644 drivers/soc/qcom/rpmpd.c
drivers/soc/qcom/Kconfig +9 -0
index fcbf8a2e4080..df5cd9fa0d5e 100644
@@ -98,6 +98,15 @@ config QCOM_RPMH
 	  of hardware components aggregate requests for these resources and
 	  help apply the aggregated state on the resource.
 
+config QCOM_RPMPD
+	bool "Qualcomm RPM Power domain driver"
+	depends on MFD_QCOM_RPM && QCOM_SMD_RPM
+	help
+	  QCOM RPM Power domain driver to support power-domains with
+	  performance states. The driver communicates a performance state
+	  value to RPM which then translates it into corresponding voltage
+	  for the voltage rail.
+
 config QCOM_SMEM
 	tristate "Qualcomm Shared Memory Manager (SMEM)"
 	depends on ARCH_QCOM || COMPILE_TEST
drivers/soc/qcom/Makefile +1 -0
index f25b54cd6cf8..f1b25fdcf2ad 100644
@@ -21,3 +21,4 @@ obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o
 obj-$(CONFIG_QCOM_APR) += apr.o
 obj-$(CONFIG_QCOM_LLCC) += llcc-slice.o
 obj-$(CONFIG_QCOM_SDM845_LLCC) += llcc-sdm845.o
+obj-$(CONFIG_QCOM_RPMPD) += rpmpd.o
drivers/soc/qcom/rpmpd.c new file +282 -0

282 lines not on this page · raw message

Signature · 2 lines
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
#5 lore raw

PATCH v7 4/10 soc: qcom: rpmpd: Add support for get/set performance state

In reply to Rajendra Nayak

Add support for the .set_performace_state() and .opp_to_performance_state() callbacks in the rpmpd driver.

---
 drivers/soc/qcom/rpmpd.c | 44 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)
drivers/soc/qcom/rpmpd.c +44 -0
index 7715ba7c9157..59e21c88a144 100644
@@ -10,6 +10,7 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
+#include <linux/pm_opp.h>
 #include <linux/soc/qcom/smd-rpm.h>
 
 #include <dt-bindings/mfd/qcom-rpm.h>
@@ -26,6 +27,8 @@
 #define KEY_ENABLE		0x6e657773 /* swen */
 #define KEY_FLOOR_CORNER	0x636676   /* vfc */
 
+#define MAX_RPMPD_STATE		6
+
 #define DEFINE_RPMPD_CORNER_SMPA(_platform, _name, _active, r_id)		\
 	static struct rpmpd _platform##_##_active;			\
 	static struct rpmpd _platform##_##_name = {			\
@@ -218,6 +221,45 @@ static int rpmpd_power_off(struct generic_pm_domain *domain)
 	return ret;
 }
 
+static int rpmpd_set_performance(struct generic_pm_domain *domain,
+				 unsigned int state)
+{
+	int ret = 0;
+	struct rpmpd *pd = domain_to_rpmpd(domain);
+
+	if (state > MAX_RPMPD_STATE)
+		goto out;
+
+	mutex_lock(&rpmpd_lock);
+
+	pd->corner = state;
+
+	if (!pd->enabled && pd->key != KEY_FLOOR_CORNER)
+		goto out;
+
+	ret = rpmpd_aggregate_corner(pd);
+
+out:
+	mutex_unlock(&rpmpd_lock);
+
+	return ret;
+}
+
+static unsigned int rpmpd_get_performance(struct generic_pm_domain *genpd,
+					  struct dev_pm_opp *opp)
+{
+	struct device_node *np;
+	unsigned int corner = 0;
+
+	np = dev_pm_opp_get_of_node(opp);
+	if (of_property_read_u32(np, "qcom,level", &corner))
+		pr_err("%s: missing 'qcom,level' property\n", __func__);
+
+	of_node_put(np);
+
+	return corner;
+}
+
 static int rpmpd_probe(struct platform_device *pdev)
 {
 	int i;
@@ -258,6 +300,8 @@ static int rpmpd_probe(struct platform_device *pdev)
 		rpmpds[i]->rpm = rpm;
 		rpmpds[i]->pd.power_off = rpmpd_power_off;
 		rpmpds[i]->pd.power_on = rpmpd_power_on;
+		rpmpds[i]->pd.set_performance_state = rpmpd_set_performance;
+		rpmpds[i]->pd.opp_to_performance_state = rpmpd_get_performance;
 		pm_genpd_init(&rpmpds[i]->pd, NULL, true);
 
 		data->domains[i] = &rpmpds[i]->pd;
Signature · 2 lines
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
Reviewed-by on v7 4/10
#6 lore raw

Re: [PATCH v7 04/10] soc: qcom: rpmpd: Add support for get/set performance state

Quoting Rajendra Nayak (2018-12-12 01:21:25)

Quoted 7 lines

Add support for the .set_performace_state() and .opp_to_performance_state() callbacks in the rpmpd driver.

---

#7 lore raw

PATCH v7 5/10 arm64: dts: msm8996: Add rpmpd device node

In reply to Rajendra Nayak

Add rpmpd device node and its OPP table

---
 arch/arm64/boot/dts/qcom/msm8996.dtsi | 34 +++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)
arch/arm64/boot/dts/qcom/msm8996.dtsi +34 -0
index 99b7495455a6..cac70623600f 100644
@@ -306,6 +306,40 @@
 				#clock-cells = <1>;
 			};
 
+			rpmpd: power-controller {
+				compatible = "qcom,msm8996-rpmpd";
+				#power-domain-cells = <1>;
+				operating-points-v2 = <&rpmpd_opp_table>;
+
+				rpmpd_opp_table: opp-table {
+					compatible = "operating-points-v2-qcom-level";
+
+					rpmpd_opp1: opp1 {
+						qcom,level = <1>;
+					};
+
+					rpmpd_opp2: opp2 {
+						qcom,level = <2>;
+					};
+
+					rpmpd_opp3: opp3 {
+						qcom,level = <3>;
+					};
+
+					rpmpd_opp4: opp4 {
+						qcom,level = <4>;
+					};
+
+					rpmpd_opp5: opp5 {
+						qcom,level = <5>;
+					};
+
+					rpmpd_opp6: opp6 {
+						qcom,level = <6>;
+					};
+				};
+			};
+
 			pm8994-regulators {
 				compatible = "qcom,rpm-pm8994-regulators";
 
Signature · 2 lines
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
#8 lore raw

PATCH v7 6/10 soc: qcom: rpmhpd: Add RPMh power domain driver

In reply to Rajendra Nayak

The RPMh power domain driver aggregates the corner votes from various consumers for the ARC resources and communicates it to RPMh.

With RPMh we use 2 different numbering space for corners, one used by the clients to express their performance needs, and another used to communicate to RPMh hardware.

The clients express their performance requirements using a sparse numbering space which are mapped to meaningful levels like RET, SVS, NOMINAL, TURBO etc which then get mapped to another number space between 0 and 15 which is communicated to RPMh. The sparse number space, also referred to as vlvl is mapped to the continuous number space of 0 to 15, also referred to as hlvl, using command DB.

Some power domain clients could request a performance state only while the CPU is active, while some others could request for a certain performance state all the time regardless of the state of the CPU. We handle this by internally aggregating the votes from both type of clients and then send the aggregated votes to RPMh.

There are also 3 different types of votes that are comunicated to RPMh for every resource.
1. ACTIVE_ONLY:
This specifies the requirement for the resource when the CPU is active
2. SLEEP:
This specifies the requirement for the resource when the CPU is going to sleep
3. WAKE_ONLY:
This specifies the requirement for the resource when the CPU is coming out of sleep to active state

We add data for all power domains on sdm845 SoC as part of the patch. The driver can be extended to support other SoCs which support RPMh

---
 drivers/soc/qcom/Kconfig  |   9 +
 drivers/soc/qcom/Makefile |   1 +
 drivers/soc/qcom/rpmhpd.c | 400 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 410 insertions(+)
 create mode 100644 drivers/soc/qcom/rpmhpd.c
drivers/soc/qcom/Kconfig +9 -0
index df5cd9fa0d5e..6241d3e3b115 100644
@@ -98,6 +98,15 @@ config QCOM_RPMH
 	  of hardware components aggregate requests for these resources and
 	  help apply the aggregated state on the resource.
 
+config QCOM_RPMHPD
+	bool "Qualcomm RPMh Power domain driver"
+	depends on QCOM_RPMH && QCOM_COMMAND_DB
+	help
+	  QCOM RPMh Power domain driver to support power-domains with
+	  performance states. The driver communicates a performance state
+	  value to RPMh which then translates it into corresponding voltage
+	  for the voltage rail.
+
 config QCOM_RPMPD
 	bool "Qualcomm RPM Power domain driver"
 	depends on MFD_QCOM_RPM && QCOM_SMD_RPM
drivers/soc/qcom/Makefile +1 -0
index f1b25fdcf2ad..ffe519b0cb66 100644
@@ -21,4 +21,5 @@ obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o
 obj-$(CONFIG_QCOM_APR) += apr.o
 obj-$(CONFIG_QCOM_LLCC) += llcc-slice.o
 obj-$(CONFIG_QCOM_SDM845_LLCC) += llcc-sdm845.o
+obj-$(CONFIG_QCOM_RPMHPD) += rpmhpd.o
 obj-$(CONFIG_QCOM_RPMPD) += rpmpd.o
drivers/soc/qcom/rpmhpd.c new file +400 -0

400 lines not on this page · raw message

Signature · 2 lines
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
Reviewed-by on v7 6/10
#9 lore raw

Re: [PATCH v7 06/10] soc: qcom: rpmhpd: Add RPMh power domain driver

Quoting Rajendra Nayak (2018-12-12 01:21:27)

Quoted 32 lines

The RPMh power domain driver aggregates the corner votes from various consumers for the ARC resources and communicates it to RPMh.

With RPMh we use 2 different numbering space for corners, one used by the clients to express their performance needs, and another used to communicate to RPMh hardware.

The clients express their performance requirements using a sparse numbering space which are mapped to meaningful levels like RET, SVS, NOMINAL, TURBO etc which then get mapped to another number space between 0 and 15 which is communicated to RPMh. The sparse number space, also referred to as vlvl is mapped to the continuous number space of 0 to 15, also referred to as hlvl, using command DB.

Some power domain clients could request a performance state only while the CPU is active, while some others could request for a certain performance state all the time regardless of the state of the CPU. We handle this by internally aggregating the votes from both type of clients and then send the aggregated votes to RPMh.

There are also 3 different types of votes that are comunicated to RPMh for every resource.
1. ACTIVE_ONLY:
This specifies the requirement for the resource when the CPU is active
2. SLEEP:
This specifies the requirement for the resource when the CPU is going to sleep
3. WAKE_ONLY:
This specifies the requirement for the resource when the CPU is coming out of sleep to active state

Quoted 6 lines

We add data for all power domains on sdm845 SoC as part of the patch. The driver can be extended to support other SoCs which support RPMh

---

#10 lore raw

PATCH v7 7/10 arm64: dts: sdm845: Add rpmh powercontroller node

In reply to Rajendra Nayak

Add the DT node for the rpmhpd powercontroller.

---
 arch/arm64/boot/dts/qcom/sdm845.dtsi | 51 ++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)
arch/arm64/boot/dts/qcom/sdm845.dtsi +51 -0
index c27cbd3bcb0a..26e8011304d0 100644
@@ -10,6 +10,7 @@
 #include <dt-bindings/clock/qcom,rpmh.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/phy/phy-qcom-qusb2.h>
+#include <dt-bindings/power/qcom-rpmpd.h>
 #include <dt-bindings/reset/qcom,sdm845-aoss.h>
 #include <dt-bindings/soc/qcom,rpmh-rsc.h>
 #include <dt-bindings/clock/qcom,gcc-sdm845.h>
@@ -1602,6 +1603,56 @@
 				compatible = "qcom,sdm845-rpmh-clk";
 				#clock-cells = <1>;
 			};
+
+			rpmhpd: power-controller {
+				compatible = "qcom,sdm845-rpmhpd";
+				#power-domain-cells = <1>;
+				operating-points-v2 = <&rpmhpd_opp_table>;
+
+				rpmhpd_opp_table: opp-table {
+					compatible = "operating-points-v2-qcom-level";
+
+					rpmhpd_opp_ret: opp1 {
+						qcom,level = <RPMH_REGULATOR_LEVEL_RETENTION>;
+					};
+
+					rpmhpd_opp_min_svs: opp2 {
+						qcom,level = <RPMH_REGULATOR_LEVEL_MIN_SVS>;
+					};
+
+					rpmhpd_opp_low_svs: opp3 {
+						qcom,level = <RPMH_REGULATOR_LEVEL_LOW_SVS>;
+					};
+
+					rpmhpd_opp_svs: opp4 {
+						qcom,level = <RPMH_REGULATOR_LEVEL_SVS>;
+					};
+
+					rpmhpd_opp_svs_l1: opp5 {
+						qcom,level = <RPMH_REGULATOR_LEVEL_SVS_L1>;
+					};
+
+					rpmhpd_opp_nom: opp6 {
+						qcom,level = <RPMH_REGULATOR_LEVEL_NOM>;
+					};
+
+					rpmhpd_opp_nom_l1: opp7 {
+						qcom,level = <RPMH_REGULATOR_LEVEL_NOM_L1>;
+					};
+
+					rpmhpd_opp_nom_l2: opp8 {
+						qcom,level = <RPMH_REGULATOR_LEVEL_NOM_L2>;
+					};
+
+					rpmhpd_opp_turbo: opp9 {
+						qcom,level = <RPMH_REGULATOR_LEVEL_TURBO>;
+					};
+
+					rpmhpd_opp_turbo_l1: opp10 {
+						qcom,level = <RPMH_REGULATOR_LEVEL_TURBO_L1>;
+					};
+				};
+			};
 		};
 
 		intc: interrupt-controller@17a00000 {
Signature · 2 lines
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
#11 lore raw

PATCH v7 8/10 PM / Domains: Add a simple_opp_to_performance_state() helper

In reply to Rajendra Nayak

Now that we have atleast 2 genpd providers, both using a simple routine to read a performance state value from device tree and return it, in order to implement the .opp_to_performance_state callback, add a simple_opp_to_performance_state() helper to do it, so it can be resued across all such genpd providers which just need to read the value from DT.

---
 drivers/base/power/domain.c | 17 +++++++++++++++++
 include/linux/pm_domain.h   |  9 +++++++++
 2 files changed, 26 insertions(+)
drivers/base/power/domain.c +17 -0
index 8e554e6a82a2..193872afbe20 100644
@@ -2520,6 +2520,23 @@ int of_genpd_parse_idle_states(struct device_node *dn,
 }
 EXPORT_SYMBOL_GPL(of_genpd_parse_idle_states);
 
+unsigned int simple_opp_to_performance_state(struct generic_pm_domain *genpd,
+					     struct dev_pm_opp *opp,
+					     const char *name)
+{
+	struct device_node *np;
+	unsigned int perf_state = 0;
+
+	np = dev_pm_opp_get_of_node(opp);
+	if (of_property_read_u32(np, name, &perf_state))
+		pr_err("%s: missing %s property\n", __func__, name);
+
+	of_node_put(np);
+
+	return perf_state;
+}
+EXPORT_SYMBOL_GPL(simple_opp_to_performance_state);
+
 /**
  * pm_genpd_opp_to_performance_state - Gets performance state of the genpd from its OPP node.
  *
include/linux/pm_domain.h +9 -0
index 642036952553..7e5777b081ee 100644
@@ -260,6 +260,9 @@ int of_genpd_parse_idle_states(struct device_node *dn,
 			       struct genpd_power_state **states, int *n);
 unsigned int pm_genpd_opp_to_performance_state(struct device *genpd_dev,
 					       struct dev_pm_opp *opp);
+unsigned int simple_opp_to_performance_state(struct  generic_pm_domain *genpd,
+					     struct dev_pm_opp *opp,
+					     const char *name);
 
 int genpd_dev_pm_attach(struct device *dev);
 struct device *genpd_dev_pm_attach_by_id(struct device *dev,
@@ -306,6 +309,12 @@ pm_genpd_opp_to_performance_state(struct device *genpd_dev,
 	return 0;
 }
 
+unsigned int simple_opp_to_performance_state(struct generic_pm_domain *genpd,
+					     struct dev_pm_opp *opp,
+					     const char *name)
+{
+	return 0;
+}
 static inline int genpd_dev_pm_attach(struct device *dev)
 {
 	return 0;
Signature · 2 lines
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
#12 lore raw

PATCH v7 9/10 soc: qcom: rpmpd: Use simple_opp_to_performance_state() helper

In reply to Rajendra Nayak

Get rid of the duplicate code across rpmpd and rpmhpd to read the performance state value from Device tree and use the simple_opp_to_performance_state() helper instead.

---
 drivers/soc/qcom/rpmhpd.c | 11 +----------
 drivers/soc/qcom/rpmpd.c  | 11 +----------
 2 files changed, 2 insertions(+), 20 deletions(-)
drivers/soc/qcom/rpmhpd.c +1 -10
index e37976e87370..f7fbe57f31ae 100644
@@ -276,16 +276,7 @@ static int rpmhpd_set_performance_state(struct generic_pm_domain *domain,
 static unsigned int rpmhpd_get_performance_state(struct generic_pm_domain *genpd,
 						 struct dev_pm_opp *opp)
 {
-	struct device_node *np;
-	unsigned int level = 0;
-
-	np = dev_pm_opp_get_of_node(opp);
-	if (of_property_read_u32(np, "qcom,level", &level))
-		pr_err("%s: missing 'qcom,level' property\n", __func__);
-
-	of_node_put(np);
-
-	return level;
+	return simple_opp_to_performance_state(genpd, opp, "qcom,level");
 }
 
 static int rpmhpd_update_level_mapping(struct rpmhpd *rpmhpd)
drivers/soc/qcom/rpmpd.c +1 -10
index 59e21c88a144..29288af502b0 100644
@@ -248,16 +248,7 @@ static int rpmpd_set_performance(struct generic_pm_domain *domain,
 static unsigned int rpmpd_get_performance(struct generic_pm_domain *genpd,
 					  struct dev_pm_opp *opp)
 {
-	struct device_node *np;
-	unsigned int corner = 0;
-
-	np = dev_pm_opp_get_of_node(opp);
-	if (of_property_read_u32(np, "qcom,level", &corner))
-		pr_err("%s: missing 'qcom,level' property\n", __func__);
-
-	of_node_put(np);
-
-	return corner;
+	return simple_opp_to_performance_state(genpd, opp, "qcom,level");
 }
 
 static int rpmpd_probe(struct platform_device *pdev)
Signature · 2 lines
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
#13 lore raw

PATCH v7 10/10 soc: qcom: rpmhpd: Mark mx as a parent for cx

In reply to Rajendra Nayak

Specify the active + sleep and active-only MX power domains as the parents of the corresponding CX power domains. This will ensure that performance state requests on CX automatically generate equivalent requests on MX power domains.

This is used to enforce a requirement that exists for various hardware blocks on SDM845 that MX performance state >= CX performance state for a given operating frequency.

---
This patch is dependent on the series from
Viresh [1] which adds support to propogate performance states across the power domain hierarchy which is still being reviewed.

[1] https://lkml.org/lkml/2018/11/26/333

 drivers/soc/qcom/rpmhpd.c | 11 +++++++++++
 1 file changed, 11 insertions(+)
drivers/soc/qcom/rpmhpd.c +11 -0
index f7fbe57f31ae..71d693c31e3b 100644
@@ -97,12 +97,14 @@ static struct rpmhpd sdm845_cx_ao;
 static struct rpmhpd sdm845_cx = {
 	.pd = { .name = "cx", },
 	.peer = &sdm845_cx_ao,
+	.parent = &sdm845_mx.pd,
 	.res_name = "cx.lvl",
 };
 
 static struct rpmhpd sdm845_cx_ao = {
 	.pd = { .name = "cx_ao", },
 	.peer = &sdm845_cx,
+	.parent = &sdm845_mx_ao.pd,
 	.res_name = "cx.lvl",
 };
 
@@ -372,6 +374,15 @@ static int rpmhpd_probe(struct platform_device *pdev)
 		data->domains[i] = &rpmhpds[i]->pd;
 	}
 
+	/* Add subdomains */
+	for (i = 0; i < num_pds; i++) {
+		if (!rpmhpds[i])
+			continue;
+		if (rpmhpds[i]->parent)
+			pm_genpd_add_subdomain(rpmhpds[i]->parent,
+					       &rpmhpds[i]->pd);
+	}
+
 	return of_genpd_add_provider_onecell(pdev->dev.of_node, data);
 }
 
Signature · 2 lines
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
Reviewed-by on v7 10/10
#14 lore raw

Re: [PATCH v7 10/10] soc: qcom: rpmhpd: Mark mx as a parent for cx

Quoting Rajendra Nayak (2018-12-12 01:21:31)

Quoted 5 lines

Specify the active + sleep and active-only MX power domains as the parents of the corresponding CX power domains. This will ensure that performance state requests on CX automatically generate equivalent requests on MX power domains.

Quoted 7 lines

This is used to enforce a requirement that exists for various hardware blocks on SDM845 that MX performance state >= CX performance state for a given operating frequency.

---

#15 lore raw
In reply to Rajendra Nayak
Quoted 2 lines

Changes in v7:
* Rebased on Andy's for-next, and used the updated cmd_db_read_aux_data()

[]..

Hey Andy, just wanted to let you know that this series (v7) is now well reviewed/ack'ed and ready to land (except for the last 3 patches) Patch 08/10 will need to go via Ulf/Rafael and Patch 09/10 depends on it for compilation, also Patch 10/10 has other dependencies which need to land via the power tree.

So Patch 01/10 to 07/10 from this series are good to be pulled in, whenever you think is the right time, I am guessing its probably too late for 4.21?

Thanks,
Rajendra

Quoted 86 lines

Changes in v6:
* OPP binding updates for qcom,level reviewed by Rob
* DT bindings for rpmpd and rpmhpd updated to specify the OPP tables as child nodes of the power-controller itself
* Removed some module specific remains from the drivers, now that they can only be built-in
* Added a simple_opp_to_performance_state() helper

Changes in v5:
* First 6 patches are unchanged
* Patch 7/8 adds the DT node for rpmh power-controller on sdm845 and the corresponding OPP tables for it to describe the performance states
* Patch 8/8 adds a parent/child relationship across mx/cx and mx_ao/cx_ao as needed on sdm845 platform. This patch is dependent on the series from Viresh [1] which adds support to propogate performance states across the power domain hierarchy which is still being reviewed

Changes in v4:
* Included the patch to add qcom-opp bindings (dropped accidentally in v3)
* merged the patches to add bindings for rpm and rpmh, added consumer binding example
* Made the drivers built in, removed .remove
* Added better description in changelog for PATCH 6/6
* Updated rpmhpd_aggregate_corner() based on Davids feedback
* rpmhpd_set_performance_state() returns max corner, in cases where its called with an INT_MAX
* Dropped the patch to max vote on all corners at init, the patch did not work anyway, and it shouldn't be needed now

Changes in v3:
* Bindings split into seperate patches
* Bindings updated to remove duplicate OPP table phandles
* DT headers defining macros for Power domain indexes and OPP levels
* Optimisations to use rpmh_write_async() whereever applicable
* Fixed up handling of ACTIVE_ONLY/WAKE_ONLY/SLEEP voting for RPMh
* Fixed the vlvl to hlvl conversions in set_performance
* Other minor fixes based on review of v2
* TODO: This series does not handle the case where all VDD_MX votes should be higher than VDD_CX from APPs, as pointed out
by David Collins in v2. This needs support at genpd to propogate performance state up the parents, if we model these as Parent/Child to handle the interdependency.

Changes in v2:
* added a power domain driver for sdm845 which supports communicating to RPMh
* dropped the changes to sdhc driver to move over to using OPP
as there is active discussion on using OPP as the interface vs handling all of it in clock drivers
* Other minor binding updates based on review of v1

With performance state support for genpd/OPP merged, this is an effort to model a power domain driver to communicate corner/level values for qualcomm platforms to RPM (Remote Power Manager) and RPMh.

[1] https://lkml.org/lkml/2018/11/26/333

Rajendra Nayak (10):
dt-bindings: opp: Introduce qcom-opp bindings
dt-bindings: power: Add qcom rpm power domain driver bindings
soc: qcom: rpmpd: Add a Power domain driver to model corners
soc: qcom: rpmpd: Add support for get/set performance state
arm64: dts: msm8996: Add rpmpd device node
soc: qcom: rpmhpd: Add RPMh power domain driver
arm64: dts: sdm845: Add rpmh powercontroller node
PM / Domains: Add a simple_opp_to_performance_state() helper
soc: qcom: rpmpd: Use simple_opp_to_performance_state() helper
soc: qcom: rpmhpd: Mark mx as a parent for cx

  .../devicetree/bindings/opp/qcom-opp.txt      |  25 ++
  .../devicetree/bindings/power/qcom,rpmpd.txt  | 146 +++++++
  arch/arm64/boot/dts/qcom/msm8996.dtsi         |  34 ++
  arch/arm64/boot/dts/qcom/sdm845.dtsi          |  51 +++
  drivers/base/power/domain.c                   |  17 +
  drivers/soc/qcom/Kconfig                      |  18 +
  drivers/soc/qcom/Makefile                     |   2 +
  drivers/soc/qcom/rpmhpd.c                     | 402 ++++++++++++++++++
  drivers/soc/qcom/rpmpd.c                      | 317 ++++++++++++++
  include/dt-bindings/power/qcom-rpmpd.h        |  39 ++
  include/linux/pm_domain.h                     |   9 +
  11 files changed, 1060 insertions(+)

create mode 100644 Documentation/devicetree/bindings/opp/qcom-opp.txt create mode 100644 Documentation/devicetree/bindings/power/qcom,rpmpd.txt create mode 100644 drivers/soc/qcom/rpmhpd.c
create mode 100644 drivers/soc/qcom/rpmpd.c
create mode 100644 include/dt-bindings/power/qcom-rpmpd.h