linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v6 00/10] Add power domain driver for corners on msm8996/sdm845
@ 2018-12-11  9:49 Rajendra Nayak
  2018-12-11  9:49 ` [PATCH v6 01/10] dt-bindings: opp: Introduce qcom-opp bindings Rajendra Nayak
                   ` (10 more replies)
  0 siblings, 11 replies; 27+ messages in thread
From: Rajendra Nayak @ 2018-12-11  9:49 UTC (permalink / raw)
  To: andy.gross, robh, viresh.kumar, sboyd, ulf.hansson, collinsd, mka
  Cc: devicetree, linux-arm-msm, linux-kernel, Rajendra Nayak

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                     | 419 ++++++++++++++++++
 drivers/soc/qcom/rpmpd.c                      | 317 +++++++++++++
 include/dt-bindings/power/qcom-rpmpd.h        |  39 ++
 include/linux/pm_domain.h                     |   9 +
 11 files changed, 1077 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

-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation


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

* [PATCH v6 01/10] dt-bindings: opp: Introduce qcom-opp bindings
  2018-12-11  9:49 [PATCH v6 00/10] Add power domain driver for corners on msm8996/sdm845 Rajendra Nayak
@ 2018-12-11  9:49 ` Rajendra Nayak
  2018-12-11  9:49 ` [PATCH v6 02/10] dt-bindings: power: Add qcom rpm power domain driver bindings Rajendra Nayak
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 27+ messages in thread
From: Rajendra Nayak @ 2018-12-11  9:49 UTC (permalink / raw)
  To: andy.gross, robh, viresh.kumar, sboyd, ulf.hansson, collinsd, mka
  Cc: devicetree, linux-arm-msm, linux-kernel, Rajendra Nayak

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.

Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Stephen Boyd <swboyd@chromium.org>
Reviewed-by: Rob Herring <robh@kernel.org>
---
 .../devicetree/bindings/opp/qcom-opp.txt      | 25 +++++++++++++++++++
 1 file changed, 25 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/opp/qcom-opp.txt

diff --git a/Documentation/devicetree/bindings/opp/qcom-opp.txt b/Documentation/devicetree/bindings/opp/qcom-opp.txt
new file mode 100644
index 000000000000..db4d970c7ec7
--- /dev/null
+++ b/Documentation/devicetree/bindings/opp/qcom-opp.txt
@@ -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.
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation


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

* [PATCH v6 02/10] dt-bindings: power: Add qcom rpm power domain driver bindings
  2018-12-11  9:49 [PATCH v6 00/10] Add power domain driver for corners on msm8996/sdm845 Rajendra Nayak
  2018-12-11  9:49 ` [PATCH v6 01/10] dt-bindings: opp: Introduce qcom-opp bindings Rajendra Nayak
@ 2018-12-11  9:49 ` Rajendra Nayak
  2018-12-11 21:28   ` Stephen Boyd
  2018-12-11  9:49 ` [PATCH v6 03/10] soc: qcom: rpmpd: Add a Power domain driver to model corners Rajendra Nayak
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 27+ messages in thread
From: Rajendra Nayak @ 2018-12-11  9:49 UTC (permalink / raw)
  To: andy.gross, robh, viresh.kumar, sboyd, ulf.hansson, collinsd, mka
  Cc: devicetree, linux-arm-msm, linux-kernel, 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.

Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
---
 .../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

diff --git a/Documentation/devicetree/bindings/power/qcom,rpmpd.txt b/Documentation/devicetree/bindings/power/qcom,rpmpd.txt
new file mode 100644
index 000000000000..a776e4407f09
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/qcom,rpmpd.txt
@@ -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>;
+		};
+
+	};
diff --git a/include/dt-bindings/power/qcom-rpmpd.h b/include/dt-bindings/power/qcom-rpmpd.h
new file mode 100644
index 000000000000..87d9c6611682
--- /dev/null
+++ b/include/dt-bindings/power/qcom-rpmpd.h
@@ -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
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation


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

* [PATCH v6 03/10] soc: qcom: rpmpd: Add a Power domain driver to model corners
  2018-12-11  9:49 [PATCH v6 00/10] Add power domain driver for corners on msm8996/sdm845 Rajendra Nayak
  2018-12-11  9:49 ` [PATCH v6 01/10] dt-bindings: opp: Introduce qcom-opp bindings Rajendra Nayak
  2018-12-11  9:49 ` [PATCH v6 02/10] dt-bindings: power: Add qcom rpm power domain driver bindings Rajendra Nayak
@ 2018-12-11  9:49 ` Rajendra Nayak
  2018-12-11 21:52   ` Stephen Boyd
  2018-12-11  9:49 ` [PATCH v6 04/10] soc: qcom: rpmpd: Add support for get/set performance state Rajendra Nayak
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 27+ messages in thread
From: Rajendra Nayak @ 2018-12-11  9:49 UTC (permalink / raw)
  To: andy.gross, robh, viresh.kumar, sboyd, ulf.hansson, collinsd, mka
  Cc: devicetree, linux-arm-msm, linux-kernel, 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.

Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
Acked-by: Rob Herring <robh@kernel.org>
---
 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

diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 684cb51694d1..e9b60695f6e7 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -103,6 +103,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
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index f25b54cd6cf8..f1b25fdcf2ad 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -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
diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c
new file mode 100644
index 000000000000..7715ba7c9157
--- /dev/null
+++ b/drivers/soc/qcom/rpmpd.c
@@ -0,0 +1,282 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/pm_domain.h>
+#include <linux/mfd/qcom_rpm.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/soc/qcom/smd-rpm.h>
+
+#include <dt-bindings/mfd/qcom-rpm.h>
+#include <dt-bindings/power/qcom-rpmpd.h>
+
+#define domain_to_rpmpd(domain) container_of(domain, struct rpmpd, pd)
+
+/* Resource types */
+#define RPMPD_SMPA 0x61706d73
+#define RPMPD_LDOA 0x616f646c
+
+/* Operation Keys */
+#define KEY_CORNER		0x6e726f63 /* corn */
+#define KEY_ENABLE		0x6e657773 /* swen */
+#define KEY_FLOOR_CORNER	0x636676   /* vfc */
+
+#define DEFINE_RPMPD_CORNER_SMPA(_platform, _name, _active, r_id)		\
+	static struct rpmpd _platform##_##_active;			\
+	static struct rpmpd _platform##_##_name = {			\
+		.pd = {	.name = #_name,	},				\
+		.peer = &_platform##_##_active,				\
+		.res_type = RPMPD_SMPA,					\
+		.res_id = r_id,						\
+		.key = KEY_CORNER,					\
+	};								\
+	static struct rpmpd _platform##_##_active = {			\
+		.pd = { .name = #_active, },				\
+		.peer = &_platform##_##_name,				\
+		.active_only = true,					\
+		.res_type = RPMPD_SMPA,					\
+		.res_id = r_id,						\
+		.key = KEY_CORNER,					\
+	}
+
+#define DEFINE_RPMPD_CORNER_LDOA(_platform, _name, r_id)			\
+	static struct rpmpd _platform##_##_name = {			\
+		.pd = { .name = #_name, },				\
+		.res_type = RPMPD_LDOA,					\
+		.res_id = r_id,						\
+		.key = KEY_CORNER,					\
+	}
+
+#define DEFINE_RPMPD_VFC(_platform, _name, r_id, r_type)		\
+	static struct rpmpd _platform##_##_name = {			\
+		.pd = { .name = #_name, },				\
+		.res_type = r_type,					\
+		.res_id = r_id,						\
+		.key = KEY_FLOOR_CORNER,				\
+	}
+
+#define DEFINE_RPMPD_VFC_SMPA(_platform, _name, r_id)			\
+	DEFINE_RPMPD_VFC(_platform, _name, r_id, RPMPD_SMPA)
+
+#define DEFINE_RPMPD_VFC_LDOA(_platform, _name, r_id)			\
+	DEFINE_RPMPD_VFC(_platform, _name, r_id, RPMPD_LDOA)
+
+struct rpmpd_req {
+	__le32 key;
+	__le32 nbytes;
+	__le32 value;
+};
+
+struct rpmpd {
+	struct generic_pm_domain pd;
+	struct rpmpd *peer;
+	const bool active_only;
+	unsigned int corner;
+	bool enabled;
+	const char *res_name;
+	const int res_type;
+	const int res_id;
+	struct qcom_smd_rpm *rpm;
+	__le32 key;
+};
+
+struct rpmpd_desc {
+	struct rpmpd **rpmpds;
+	size_t num_pds;
+};
+
+static DEFINE_MUTEX(rpmpd_lock);
+
+/* msm8996 RPM Power domains */
+DEFINE_RPMPD_CORNER_SMPA(msm8996, vddcx, vddcx_ao, 1);
+DEFINE_RPMPD_CORNER_SMPA(msm8996, vddmx, vddmx_ao, 2);
+DEFINE_RPMPD_CORNER_LDOA(msm8996, vddsscx, 26);
+
+DEFINE_RPMPD_VFC_SMPA(msm8996, vddcx_vfc, 1);
+DEFINE_RPMPD_VFC_LDOA(msm8996, vddsscx_vfc, 26);
+
+static struct rpmpd *msm8996_rpmpds[] = {
+	[MSM8996_VDDCX] =	&msm8996_vddcx,
+	[MSM8996_VDDCX_AO] =	&msm8996_vddcx_ao,
+	[MSM8996_VDDCX_VFC] =	&msm8996_vddcx_vfc,
+	[MSM8996_VDDMX] =	&msm8996_vddmx,
+	[MSM8996_VDDMX_AO] =	&msm8996_vddmx_ao,
+	[MSM8996_VDDSSCX] =	&msm8996_vddsscx,
+	[MSM8996_VDDSSCX_VFC] =	&msm8996_vddsscx_vfc,
+};
+
+static const struct rpmpd_desc msm8996_desc = {
+	.rpmpds = msm8996_rpmpds,
+	.num_pds = ARRAY_SIZE(msm8996_rpmpds),
+};
+
+static const struct of_device_id rpmpd_match_table[] = {
+	{ .compatible = "qcom,msm8996-rpmpd", .data = &msm8996_desc },
+	{ }
+};
+
+static int rpmpd_send_enable(struct rpmpd *pd, bool enable)
+{
+	struct rpmpd_req req = {
+		.key = KEY_ENABLE,
+		.nbytes = cpu_to_le32(sizeof(u32)),
+		.value = cpu_to_le32(enable),
+	};
+
+	return qcom_rpm_smd_write(pd->rpm, QCOM_RPM_ACTIVE_STATE, pd->res_type,
+				  pd->res_id, &req, sizeof(req));
+}
+
+static int rpmpd_send_corner(struct rpmpd *pd, int state, unsigned int corner)
+{
+	struct rpmpd_req req = {
+		.key = pd->key,
+		.nbytes = cpu_to_le32(sizeof(u32)),
+		.value = cpu_to_le32(corner),
+	};
+
+	return qcom_rpm_smd_write(pd->rpm, state, pd->res_type, pd->res_id,
+				  &req, sizeof(req));
+};
+
+static void to_active_sleep(struct rpmpd *pd, unsigned int corner,
+			    unsigned int *active, unsigned int *sleep)
+{
+	*active = corner;
+
+	if (pd->active_only)
+		*sleep = 0;
+	else
+		*sleep = *active;
+}
+
+static int rpmpd_aggregate_corner(struct rpmpd *pd)
+{
+	int ret;
+	struct rpmpd *peer = pd->peer;
+	unsigned int active_corner, sleep_corner;
+	unsigned int this_active_corner = 0, this_sleep_corner = 0;
+	unsigned int peer_active_corner = 0, peer_sleep_corner = 0;
+
+	to_active_sleep(pd, pd->corner, &this_active_corner, &this_sleep_corner);
+
+	if (peer && peer->enabled)
+		to_active_sleep(peer, peer->corner, &peer_active_corner,
+				&peer_sleep_corner);
+
+	active_corner = max(this_active_corner, peer_active_corner);
+
+	ret = rpmpd_send_corner(pd, QCOM_RPM_ACTIVE_STATE, active_corner);
+	if (ret)
+		return ret;
+
+	sleep_corner = max(this_sleep_corner, peer_sleep_corner);
+
+	return rpmpd_send_corner(pd, QCOM_RPM_SLEEP_STATE, sleep_corner);
+}
+
+static int rpmpd_power_on(struct generic_pm_domain *domain)
+{
+	int ret;
+	struct rpmpd *pd = domain_to_rpmpd(domain);
+
+	mutex_lock(&rpmpd_lock);
+
+	ret = rpmpd_send_enable(pd, true);
+	if (ret)
+		goto out;
+
+	pd->enabled = true;
+
+	if (pd->corner)
+		ret = rpmpd_aggregate_corner(pd);
+
+out:
+	mutex_unlock(&rpmpd_lock);
+
+	return ret;
+}
+
+static int rpmpd_power_off(struct generic_pm_domain *domain)
+{
+	int ret;
+	struct rpmpd *pd = domain_to_rpmpd(domain);
+
+	mutex_lock(&rpmpd_lock);
+
+	ret = rpmpd_send_enable(pd, false);
+	if (!ret)
+		pd->enabled = false;
+
+	mutex_unlock(&rpmpd_lock);
+
+	return ret;
+}
+
+static int rpmpd_probe(struct platform_device *pdev)
+{
+	int i;
+	size_t num;
+	struct genpd_onecell_data *data;
+	struct qcom_smd_rpm *rpm;
+	struct rpmpd **rpmpds;
+	const struct rpmpd_desc *desc;
+
+	rpm = dev_get_drvdata(pdev->dev.parent);
+	if (!rpm) {
+		dev_err(&pdev->dev, "Unable to retrieve handle to RPM\n");
+		return -ENODEV;
+	}
+
+	desc = of_device_get_match_data(&pdev->dev);
+	if (!desc)
+		return -EINVAL;
+
+	rpmpds = desc->rpmpds;
+	num = desc->num_pds;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->domains = devm_kcalloc(&pdev->dev, num, sizeof(*data->domains),
+				     GFP_KERNEL);
+	data->num_domains = num;
+
+	for (i = 0; i < num; i++) {
+		if (!rpmpds[i]) {
+			dev_warn(&pdev->dev, "rpmpds[] with empty entry at index=%d\n",
+				 i);
+			continue;
+		}
+
+		rpmpds[i]->rpm = rpm;
+		rpmpds[i]->pd.power_off = rpmpd_power_off;
+		rpmpds[i]->pd.power_on = rpmpd_power_on;
+		pm_genpd_init(&rpmpds[i]->pd, NULL, true);
+
+		data->domains[i] = &rpmpds[i]->pd;
+	}
+
+	return of_genpd_add_provider_onecell(pdev->dev.of_node, data);
+}
+
+static struct platform_driver rpmpd_driver = {
+	.driver = {
+		.name = "qcom-rpmpd",
+		.of_match_table = rpmpd_match_table,
+		.suppress_bind_attrs = true,
+	},
+	.probe = rpmpd_probe,
+};
+
+static int __init rpmpd_init(void)
+{
+	return platform_driver_register(&rpmpd_driver);
+}
+core_initcall(rpmpd_init);
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation


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

* [PATCH v6 04/10] soc: qcom: rpmpd: Add support for get/set performance state
  2018-12-11  9:49 [PATCH v6 00/10] Add power domain driver for corners on msm8996/sdm845 Rajendra Nayak
                   ` (2 preceding siblings ...)
  2018-12-11  9:49 ` [PATCH v6 03/10] soc: qcom: rpmpd: Add a Power domain driver to model corners Rajendra Nayak
@ 2018-12-11  9:49 ` Rajendra Nayak
  2018-12-11  9:49 ` [PATCH v6 05/10] arm64: dts: msm8996: Add rpmpd device node Rajendra Nayak
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 27+ messages in thread
From: Rajendra Nayak @ 2018-12-11  9:49 UTC (permalink / raw)
  To: andy.gross, robh, viresh.kumar, sboyd, ulf.hansson, collinsd, mka
  Cc: devicetree, linux-arm-msm, linux-kernel, Rajendra Nayak

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

Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
---
 drivers/soc/qcom/rpmpd.c | 44 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c
index 7715ba7c9157..59e21c88a144 100644
--- a/drivers/soc/qcom/rpmpd.c
+++ b/drivers/soc/qcom/rpmpd.c
@@ -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;
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation


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

* [PATCH v6 05/10] arm64: dts: msm8996: Add rpmpd device node
  2018-12-11  9:49 [PATCH v6 00/10] Add power domain driver for corners on msm8996/sdm845 Rajendra Nayak
                   ` (3 preceding siblings ...)
  2018-12-11  9:49 ` [PATCH v6 04/10] soc: qcom: rpmpd: Add support for get/set performance state Rajendra Nayak
@ 2018-12-11  9:49 ` Rajendra Nayak
  2018-12-11 21:53   ` Stephen Boyd
  2018-12-11  9:49 ` [PATCH v6 06/10] soc: qcom: rpmhpd: Add RPMh power domain driver Rajendra Nayak
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 27+ messages in thread
From: Rajendra Nayak @ 2018-12-11  9:49 UTC (permalink / raw)
  To: andy.gross, robh, viresh.kumar, sboyd, ulf.hansson, collinsd, mka
  Cc: devicetree, linux-arm-msm, linux-kernel, Rajendra Nayak

Add rpmpd device node and its OPP table

Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
---
 arch/arm64/boot/dts/qcom/msm8996.dtsi | 34 +++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index b29fe80d7288..e4a84d11ace3 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -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";
 
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation


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

* [PATCH v6 06/10] soc: qcom: rpmhpd: Add RPMh power domain driver
  2018-12-11  9:49 [PATCH v6 00/10] Add power domain driver for corners on msm8996/sdm845 Rajendra Nayak
                   ` (4 preceding siblings ...)
  2018-12-11  9:49 ` [PATCH v6 05/10] arm64: dts: msm8996: Add rpmpd device node Rajendra Nayak
@ 2018-12-11  9:49 ` Rajendra Nayak
  2018-12-11 22:01   ` Stephen Boyd
  2018-12-11  9:49 ` [PATCH v6 07/10] arm64: dts: sdm845: Add rpmh powercontroller node Rajendra Nayak
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 27+ messages in thread
From: Rajendra Nayak @ 2018-12-11  9:49 UTC (permalink / raw)
  To: andy.gross, robh, viresh.kumar, sboyd, ulf.hansson, collinsd, mka
  Cc: devicetree, linux-arm-msm, linux-kernel, 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

Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
---
 drivers/soc/qcom/Kconfig  |   9 +
 drivers/soc/qcom/Makefile |   1 +
 drivers/soc/qcom/rpmhpd.c | 417 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 427 insertions(+)
 create mode 100644 drivers/soc/qcom/rpmhpd.c

diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index e9b60695f6e7..a51458022d21 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -103,6 +103,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
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index f1b25fdcf2ad..dd6ca92985ee 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -22,3 +22,4 @@ 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
+obj-$(CONFIG_QCOM_RPMHPD) += rpmhpd.o
diff --git a/drivers/soc/qcom/rpmhpd.c b/drivers/soc/qcom/rpmhpd.c
new file mode 100644
index 000000000000..f993a86be48c
--- /dev/null
+++ b/drivers/soc/qcom/rpmhpd.c
@@ -0,0 +1,417 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.*/
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/pm_domain.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_opp.h>
+#include <soc/qcom/cmd-db.h>
+#include <soc/qcom/rpmh.h>
+#include <dt-bindings/power/qcom-rpmpd.h>
+
+#define domain_to_rpmhpd(domain) container_of(domain, struct rpmhpd, pd)
+
+/*
+ * This is the number of bytes used for each command DB aux data entry of an
+ * ARC resource.
+ */
+#define RPMH_ARC_LEVEL_SIZE	2
+#define RPMH_ARC_MAX_LEVELS	16
+
+/**
+ * struct rpmhpd - top level RPMh power domain resource data structure
+ * @dev:		rpmh power domain controller device
+ * @pd: 		generic_pm_domain corrresponding to the power domain
+ * @peer:		A peer power domain in case Active only Voting is supported
+ * @active_only:	True if it represents an Active only peer
+ * @level:		An array of level (vlvl) to corner (hlvl) mappings derived from cmd-db
+ * @level_count:	Number of levels supported by the power domain. max being 16 (0 - 15)
+ * @enabled:		true if the power domain is enabled
+ * @res_name:		Resource name used for cmd-db lookup
+ * @addr:		Resource address as looped up using resource name from cmd-db
+ */
+struct rpmhpd {
+	struct device	*dev;
+	struct generic_pm_domain pd;
+	struct generic_pm_domain *parent;
+	struct rpmhpd	*peer;
+	const bool	active_only;
+	unsigned int	corner;
+	unsigned int	active_corner;
+	u32		level[RPMH_ARC_MAX_LEVELS];
+	int		level_count;
+	bool		enabled;
+	const char	*res_name;
+	u32		addr;
+};
+
+struct rpmhpd_desc {
+	struct rpmhpd **rpmhpds;
+	size_t num_pds;
+};
+
+static DEFINE_MUTEX(rpmhpd_lock);
+
+/* SDM845 RPMH powerdomains */
+
+static struct rpmhpd sdm845_ebi = {
+	.pd = { .name = "ebi", },
+	.res_name = "ebi.lvl",
+};
+
+static struct rpmhpd sdm845_lmx = {
+	.pd = { .name = "lmx", },
+	.res_name = "lmx.lvl",
+};
+
+static struct rpmhpd sdm845_lcx = {
+	.pd = { .name = "lcx", },
+	.res_name = "lcx.lvl",
+};
+
+static struct rpmhpd sdm845_gfx = {
+	.pd = { .name = "gfx", },
+	.res_name = "gfx.lvl",
+};
+
+static struct rpmhpd sdm845_mss = {
+	.pd = { .name = "mss", },
+	.res_name = "mss.lvl",
+};
+
+static struct rpmhpd sdm845_mx_ao;
+static struct rpmhpd sdm845_mx = {
+	.pd = { .name = "mx", },
+	.peer = &sdm845_mx_ao,
+	.res_name = "mx.lvl",
+};
+
+static struct rpmhpd sdm845_mx_ao = {
+	.pd = { .name = "mx_ao", },
+	.peer = &sdm845_mx,
+	.res_name = "mx.lvl",
+};
+
+static struct rpmhpd sdm845_cx_ao;
+static struct rpmhpd sdm845_cx = {
+	.pd = { .name = "cx", },
+	.peer = &sdm845_cx_ao,
+	.res_name = "cx.lvl",
+};
+
+static struct rpmhpd sdm845_cx_ao = {
+	.pd = { .name = "cx_ao", },
+	.peer = &sdm845_cx,
+	.res_name = "cx.lvl",
+};
+
+static struct rpmhpd *sdm845_rpmhpds[] = {
+	[SDM845_EBI] = &sdm845_ebi,
+	[SDM845_MX] = &sdm845_mx,
+	[SDM845_MX_AO] = &sdm845_mx_ao,
+	[SDM845_CX] = &sdm845_cx,
+	[SDM845_CX_AO] = &sdm845_cx_ao,
+	[SDM845_LMX] = &sdm845_lmx,
+	[SDM845_LCX] = &sdm845_lcx,
+	[SDM845_GFX] = &sdm845_gfx,
+	[SDM845_MSS] = &sdm845_mss,
+};
+
+static const struct rpmhpd_desc sdm845_desc = {
+	.rpmhpds = sdm845_rpmhpds,
+	.num_pds = ARRAY_SIZE(sdm845_rpmhpds),
+};
+
+static const struct of_device_id rpmhpd_match_table[] = {
+	{ .compatible = "qcom,sdm845-rpmhpd", .data = &sdm845_desc },
+	{ }
+};
+
+static int rpmhpd_send_corner(struct rpmhpd *pd, int state,
+			      unsigned int corner, bool sync)
+{
+	struct tcs_cmd cmd = {
+		.addr = pd->addr,
+		.data = corner,
+	};
+
+	/*
+	 * Wait for an ack only when we are increasing the
+	 * perf state of the power domain
+	 */
+	if (sync)
+		return rpmh_write(pd->dev, state, &cmd, 1);
+	else
+		return rpmh_write_async(pd->dev, state, &cmd, 1);
+}
+
+static void to_active_sleep(struct rpmhpd *pd, unsigned int corner,
+			    unsigned int *active, unsigned int *sleep)
+{
+	*active = corner;
+
+	if (pd->active_only)
+		*sleep = 0;
+	else
+		*sleep = *active;
+}
+
+/*
+ * This function is used to aggregate the votes across the active only
+ * resources and its peers. The aggregated votes are sent to RPMh as
+ * ACTIVE_ONLY votes (which take effect immediately), as WAKE_ONLY votes
+ * (applied by RPMh on system wakeup) and as SLEEP votes (applied by RPMh
+ * on system sleep).
+ * We send ACTIVE_ONLY votes for resources without any peers. For others,
+ * which have an active only peer, all 3 votes are sent.
+ */
+static int rpmhpd_aggregate_corner(struct rpmhpd *pd, unsigned int corner)
+{
+	int ret;
+	struct rpmhpd *peer = pd->peer;
+	unsigned int active_corner, sleep_corner;
+	unsigned int this_active_corner = 0, this_sleep_corner = 0;
+	unsigned int peer_active_corner = 0, peer_sleep_corner = 0;
+
+	to_active_sleep(pd, corner, &this_active_corner, &this_sleep_corner);
+
+	if (peer && peer->enabled)
+		to_active_sleep(peer, peer->corner, &peer_active_corner,
+				&peer_sleep_corner);
+
+	active_corner = max(this_active_corner, peer_active_corner);
+
+	ret = rpmhpd_send_corner(pd, RPMH_ACTIVE_ONLY_STATE, active_corner,
+				 active_corner > pd->active_corner);
+	if (ret)
+		return ret;
+
+	pd->active_corner = active_corner;
+
+	if (peer) {
+		peer->active_corner = active_corner;
+
+		ret = rpmhpd_send_corner(pd, RPMH_WAKE_ONLY_STATE,
+					 active_corner, false);
+		if (ret)
+			return ret;
+
+		sleep_corner = max(this_sleep_corner, peer_sleep_corner);
+
+		return rpmhpd_send_corner(pd, RPMH_SLEEP_STATE, sleep_corner,
+					  false);
+	}
+
+	return ret;
+}
+
+static int rpmhpd_power_on(struct generic_pm_domain *domain)
+{
+	struct rpmhpd *pd = domain_to_rpmhpd(domain);
+	int ret = 0;
+
+	mutex_lock(&rpmhpd_lock);
+
+	if (pd->corner)
+		ret = rpmhpd_aggregate_corner(pd, pd->corner);
+
+	if (!ret)
+		pd->enabled = true;
+
+	mutex_unlock(&rpmhpd_lock);
+
+	return ret;
+}
+
+static int rpmhpd_power_off(struct generic_pm_domain *domain)
+{
+	struct rpmhpd *pd = domain_to_rpmhpd(domain);
+	int ret = 0;
+
+	mutex_lock(&rpmhpd_lock);
+
+	ret = rpmhpd_aggregate_corner(pd, pd->level[0]);
+
+	if (!ret)
+		pd->enabled = false;
+
+	mutex_unlock(&rpmhpd_lock);
+
+	return ret;
+}
+
+static int rpmhpd_set_performance_state(struct generic_pm_domain *domain,
+					unsigned int level)
+{
+	struct rpmhpd *pd = domain_to_rpmhpd(domain);
+	int ret = 0, i;
+
+	mutex_lock(&rpmhpd_lock);
+
+	for (i = 0; i < pd->level_count; i++)
+		if (level <= pd->level[i])
+			break;
+
+	/*
+	 * If the level requested is more than that supported by the
+	 * max corner, just set it to max anyway.
+	 */
+	if (i == pd->level_count)
+		i--;
+
+	if (pd->enabled) {
+		ret = rpmhpd_aggregate_corner(pd, i);
+		if (ret)
+			goto out;
+	}
+
+	pd->corner = i;
+out:
+	mutex_unlock(&rpmhpd_lock);
+
+	return ret;
+}
+
+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;
+}
+
+static int rpmhpd_update_level_mapping(struct rpmhpd *rpmhpd)
+{
+	u8 buf[RPMH_ARC_MAX_LEVELS * RPMH_ARC_LEVEL_SIZE];
+	int i, j, len, ret;
+
+	len = cmd_db_read_aux_data_len(rpmhpd->res_name);
+	if (len <= 0)
+		return len;
+	else if (len > RPMH_ARC_MAX_LEVELS * RPMH_ARC_LEVEL_SIZE)
+		return -EINVAL;
+
+	ret = cmd_db_read_aux_data(rpmhpd->res_name, buf, len);
+	if (ret < 0)
+		return ret;
+
+	rpmhpd->level_count = len / RPMH_ARC_LEVEL_SIZE;
+
+	for (i = 0; i < rpmhpd->level_count; i++) {
+		rpmhpd->level[i] = 0;
+		for (j = 0; j < RPMH_ARC_LEVEL_SIZE; j++)
+			rpmhpd->level[i] |=
+				buf[i * RPMH_ARC_LEVEL_SIZE + j] << (8 * j);
+
+		/*
+		 * The AUX data may be zero padded.  These 0 valued entries at
+		 * the end of the map must be ignored.
+		 */
+		if (i > 0 && rpmhpd->level[i] == 0) {
+			rpmhpd->level_count = i;
+			break;
+		}
+		pr_debug("%s: ARC hlvl=%2d --> vlvl=%4u\n", rpmhpd->res_name, i,
+			 rpmhpd->level[i]);
+	}
+
+	return 0;
+}
+
+static int rpmhpd_probe(struct platform_device *pdev)
+{
+	int i, ret;
+	size_t num_pds;
+	struct device *dev = &pdev->dev;
+	struct genpd_onecell_data *data;
+	struct rpmhpd **rpmhpds;
+	const struct rpmhpd_desc *desc;
+
+	desc = of_device_get_match_data(dev);
+	if (!desc)
+		return -EINVAL;
+
+	rpmhpds = desc->rpmhpds;
+	num_pds = desc->num_pds;
+
+	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->domains = devm_kcalloc(dev, num_pds, sizeof(*data->domains),
+				     GFP_KERNEL);
+	if (!data->domains)
+		return -ENOMEM;
+
+	data->num_domains = num_pds;
+
+	ret = cmd_db_ready();
+	if (ret) {
+		if (ret != -EPROBE_DEFER)
+			dev_err(dev, "Command DB unavailable, ret=%d\n", ret);
+		return ret;
+	}
+
+	for (i = 0; i < num_pds; i++) {
+		if (!rpmhpds[i]) {
+			dev_warn(dev, "rpmhpds[%d] is empty\n", i);
+			continue;
+		}
+
+		rpmhpds[i]->dev = dev;
+		rpmhpds[i]->addr = cmd_db_read_addr(rpmhpds[i]->res_name);
+		if (!rpmhpds[i]->addr) {
+			dev_err(dev, "Could not find RPMh address for resource %s\n",
+				rpmhpds[i]->res_name);
+			return -ENODEV;
+		}
+
+		ret = cmd_db_read_slave_id(rpmhpds[i]->res_name);
+		if (ret != CMD_DB_HW_ARC) {
+			dev_err(dev, "RPMh slave ID mismatch\n");
+			return -EINVAL;
+		}
+
+		ret = rpmhpd_update_level_mapping(rpmhpds[i]);
+		if (ret)
+			return ret;
+
+		rpmhpds[i]->pd.power_off = rpmhpd_power_off;
+		rpmhpds[i]->pd.power_on = rpmhpd_power_on;
+		rpmhpds[i]->pd.set_performance_state = rpmhpd_set_performance_state;
+		rpmhpds[i]->pd.opp_to_performance_state = rpmhpd_get_performance_state;
+		pm_genpd_init(&rpmhpds[i]->pd, NULL, true);
+
+		data->domains[i] = &rpmhpds[i]->pd;
+	}
+
+	return of_genpd_add_provider_onecell(pdev->dev.of_node, data);
+}
+
+static struct platform_driver rpmhpd_driver = {
+	.driver = {
+		.name = "qcom-rpmhpd",
+		.of_match_table = rpmhpd_match_table,
+		.suppress_bind_attrs = true,
+	},
+	.probe = rpmhpd_probe,
+};
+
+static int __init rpmhpd_init(void)
+{
+	return platform_driver_register(&rpmhpd_driver);
+}
+core_initcall(rpmhpd_init);
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation


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

* [PATCH v6 07/10] arm64: dts: sdm845: Add rpmh powercontroller node
  2018-12-11  9:49 [PATCH v6 00/10] Add power domain driver for corners on msm8996/sdm845 Rajendra Nayak
                   ` (5 preceding siblings ...)
  2018-12-11  9:49 ` [PATCH v6 06/10] soc: qcom: rpmhpd: Add RPMh power domain driver Rajendra Nayak
@ 2018-12-11  9:49 ` Rajendra Nayak
  2018-12-11 22:01   ` Stephen Boyd
  2018-12-11  9:49 ` [PATCH v6 08/10] PM / Domains: Add a simple_opp_to_performance_state() helper Rajendra Nayak
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 27+ messages in thread
From: Rajendra Nayak @ 2018-12-11  9:49 UTC (permalink / raw)
  To: andy.gross, robh, viresh.kumar, sboyd, ulf.hansson, collinsd, mka
  Cc: devicetree, linux-arm-msm, linux-kernel, Rajendra Nayak

Add the DT node for the rpmhpd powercontroller.

Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 arch/arm64/boot/dts/qcom/sdm845.dtsi | 51 ++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index b72bdb0a31a5..df24f0065fdd 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -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>
 
@@ -1324,6 +1325,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 {
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation


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

* [PATCH v6 08/10] PM / Domains: Add a simple_opp_to_performance_state() helper
  2018-12-11  9:49 [PATCH v6 00/10] Add power domain driver for corners on msm8996/sdm845 Rajendra Nayak
                   ` (6 preceding siblings ...)
  2018-12-11  9:49 ` [PATCH v6 07/10] arm64: dts: sdm845: Add rpmh powercontroller node Rajendra Nayak
@ 2018-12-11  9:49 ` Rajendra Nayak
  2018-12-11 21:33   ` Stephen Boyd
  2018-12-11  9:49 ` [PATCH v6 09/10] soc: qcom: rpmpd: Use " Rajendra Nayak
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 27+ messages in thread
From: Rajendra Nayak @ 2018-12-11  9:49 UTC (permalink / raw)
  To: andy.gross, robh, viresh.kumar, sboyd, ulf.hansson, collinsd, mka
  Cc: devicetree, linux-arm-msm, linux-kernel, 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.

Suggested-by: Stephen Boyd <sboyd@kernel.org>
Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
---
 drivers/base/power/domain.c | 17 +++++++++++++++++
 include/linux/pm_domain.h   |  9 +++++++++
 2 files changed, 26 insertions(+)

diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 8e554e6a82a2..193872afbe20 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -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.
  *
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index 642036952553..7e5777b081ee 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -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;
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation


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

* [PATCH v6 09/10] soc: qcom: rpmpd: Use simple_opp_to_performance_state() helper
  2018-12-11  9:49 [PATCH v6 00/10] Add power domain driver for corners on msm8996/sdm845 Rajendra Nayak
                   ` (7 preceding siblings ...)
  2018-12-11  9:49 ` [PATCH v6 08/10] PM / Domains: Add a simple_opp_to_performance_state() helper Rajendra Nayak
@ 2018-12-11  9:49 ` Rajendra Nayak
  2018-12-11 21:34   ` Stephen Boyd
  2018-12-11  9:49 ` [PATCH v6 10/10] soc: qcom: rpmhpd: Mark mx as a parent for cx Rajendra Nayak
  2018-12-11 21:51 ` [PATCH v6 00/10] Add power domain driver for corners on msm8996/sdm845 Stephen Boyd
  10 siblings, 1 reply; 27+ messages in thread
From: Rajendra Nayak @ 2018-12-11  9:49 UTC (permalink / raw)
  To: andy.gross, robh, viresh.kumar, sboyd, ulf.hansson, collinsd, mka
  Cc: devicetree, linux-arm-msm, linux-kernel, 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.

Suggested-by: Stephen Boyd <sboyd@kernel.org>
Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
---
 drivers/soc/qcom/rpmhpd.c | 11 +----------
 drivers/soc/qcom/rpmpd.c  | 11 +----------
 2 files changed, 2 insertions(+), 20 deletions(-)

diff --git a/drivers/soc/qcom/rpmhpd.c b/drivers/soc/qcom/rpmhpd.c
index f993a86be48c..1ce86f0cc9fa 100644
--- a/drivers/soc/qcom/rpmhpd.c
+++ b/drivers/soc/qcom/rpmhpd.c
@@ -281,16 +281,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)
diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c
index 59e21c88a144..29288af502b0 100644
--- a/drivers/soc/qcom/rpmpd.c
+++ b/drivers/soc/qcom/rpmpd.c
@@ -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)
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation


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

* [PATCH v6 10/10] soc: qcom: rpmhpd: Mark mx as a parent for cx
  2018-12-11  9:49 [PATCH v6 00/10] Add power domain driver for corners on msm8996/sdm845 Rajendra Nayak
                   ` (8 preceding siblings ...)
  2018-12-11  9:49 ` [PATCH v6 09/10] soc: qcom: rpmpd: Use " Rajendra Nayak
@ 2018-12-11  9:49 ` Rajendra Nayak
  2018-12-11 10:22   ` Ulf Hansson
  2018-12-11 21:51 ` [PATCH v6 00/10] Add power domain driver for corners on msm8996/sdm845 Stephen Boyd
  10 siblings, 1 reply; 27+ messages in thread
From: Rajendra Nayak @ 2018-12-11  9:49 UTC (permalink / raw)
  To: andy.gross, robh, viresh.kumar, sboyd, ulf.hansson, collinsd, mka
  Cc: devicetree, linux-arm-msm, linux-kernel, 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.

Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
---
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(+)

diff --git a/drivers/soc/qcom/rpmhpd.c b/drivers/soc/qcom/rpmhpd.c
index 1ce86f0cc9fa..af7b07d49e4f 100644
--- a/drivers/soc/qcom/rpmhpd.c
+++ b/drivers/soc/qcom/rpmhpd.c
@@ -102,12 +102,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",
 };
 
@@ -389,6 +391,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);
 }
 
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation


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

* Re: [PATCH v6 10/10] soc: qcom: rpmhpd: Mark mx as a parent for cx
  2018-12-11  9:49 ` [PATCH v6 10/10] soc: qcom: rpmhpd: Mark mx as a parent for cx Rajendra Nayak
@ 2018-12-11 10:22   ` Ulf Hansson
  2018-12-11 10:33     ` Rajendra Nayak
  0 siblings, 1 reply; 27+ messages in thread
From: Ulf Hansson @ 2018-12-11 10:22 UTC (permalink / raw)
  To: Rajendra Nayak
  Cc: Andy Gross, Rob Herring, Viresh Kumar, Stephen Boyd,
	David Collins, Matthias Kaehlcke, DTML, linux-arm-msm,
	Linux Kernel Mailing List

On Tue, 11 Dec 2018 at 10:50, Rajendra Nayak <rnayak@codeaurora.org> wrote:
>
> 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.

I assume that also means the MX power domain must not be power off as
long as the CX power domain is powered on?

Just to make sure there are no conflicting hierarchical constraints
between idle management and performance state management!?

Kind regards
Uffe

>
> Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
> Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---
> 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(+)
>
> diff --git a/drivers/soc/qcom/rpmhpd.c b/drivers/soc/qcom/rpmhpd.c
> index 1ce86f0cc9fa..af7b07d49e4f 100644
> --- a/drivers/soc/qcom/rpmhpd.c
> +++ b/drivers/soc/qcom/rpmhpd.c
> @@ -102,12 +102,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",
>  };
>
> @@ -389,6 +391,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);
>  }
>
> --
> QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
>

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

* Re: [PATCH v6 10/10] soc: qcom: rpmhpd: Mark mx as a parent for cx
  2018-12-11 10:22   ` Ulf Hansson
@ 2018-12-11 10:33     ` Rajendra Nayak
  2018-12-11 21:50       ` Stephen Boyd
  0 siblings, 1 reply; 27+ messages in thread
From: Rajendra Nayak @ 2018-12-11 10:33 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Andy Gross, Rob Herring, Viresh Kumar, Stephen Boyd,
	David Collins, Matthias Kaehlcke, DTML, linux-arm-msm,
	Linux Kernel Mailing List



On 12/11/2018 3:52 PM, Ulf Hansson wrote:
> On Tue, 11 Dec 2018 at 10:50, Rajendra Nayak <rnayak@codeaurora.org> wrote:
>>
>> 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.
> 
> I assume that also means the MX power domain must not be power off as
> long as the CX power domain is powered on?

So with rpmh, there's really no separate on/off control, we just put
it in the lowest perf state at off.

> 
> Just to make sure there are no conflicting hierarchical constraints
> between idle management and performance state management!?
> 
> Kind regards
> Uffe
> 
>>
>> Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
>> Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
>> ---
>> 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(+)
>>
>> diff --git a/drivers/soc/qcom/rpmhpd.c b/drivers/soc/qcom/rpmhpd.c
>> index 1ce86f0cc9fa..af7b07d49e4f 100644
>> --- a/drivers/soc/qcom/rpmhpd.c
>> +++ b/drivers/soc/qcom/rpmhpd.c
>> @@ -102,12 +102,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",
>>   };
>>
>> @@ -389,6 +391,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);
>>   }
>>
>> --
>> QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
>> of Code Aurora Forum, hosted by The Linux Foundation
>>

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

* Re: [PATCH v6 02/10] dt-bindings: power: Add qcom rpm power domain driver bindings
  2018-12-11  9:49 ` [PATCH v6 02/10] dt-bindings: power: Add qcom rpm power domain driver bindings Rajendra Nayak
@ 2018-12-11 21:28   ` Stephen Boyd
  0 siblings, 0 replies; 27+ messages in thread
From: Stephen Boyd @ 2018-12-11 21:28 UTC (permalink / raw)
  To: Rajendra Nayak, andy.gross, collinsd, mka, robh, ulf.hansson,
	viresh.kumar
  Cc: devicetree, linux-arm-msm, linux-kernel, Rajendra Nayak

Quoting Rajendra Nayak (2018-12-11 01:49:30)
> 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.
> 
> Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
> ---

Reviewed-by: Stephen Boyd <swboyd@chromium.org>


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

* Re: [PATCH v6 08/10] PM / Domains: Add a simple_opp_to_performance_state() helper
  2018-12-11  9:49 ` [PATCH v6 08/10] PM / Domains: Add a simple_opp_to_performance_state() helper Rajendra Nayak
@ 2018-12-11 21:33   ` Stephen Boyd
  0 siblings, 0 replies; 27+ messages in thread
From: Stephen Boyd @ 2018-12-11 21:33 UTC (permalink / raw)
  To: Rajendra Nayak, andy.gross, collinsd, mka, robh, ulf.hansson,
	viresh.kumar
  Cc: devicetree, linux-arm-msm, linux-kernel, Rajendra Nayak

Quoting Rajendra Nayak (2018-12-11 01:49:36)
> 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.
> 
> Suggested-by: Stephen Boyd <sboyd@kernel.org>
> Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
> ---

Reviewed-by: Stephen Boyd <swboyd@chromium.org>


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

* Re: [PATCH v6 09/10] soc: qcom: rpmpd: Use simple_opp_to_performance_state() helper
  2018-12-11  9:49 ` [PATCH v6 09/10] soc: qcom: rpmpd: Use " Rajendra Nayak
@ 2018-12-11 21:34   ` Stephen Boyd
  0 siblings, 0 replies; 27+ messages in thread
From: Stephen Boyd @ 2018-12-11 21:34 UTC (permalink / raw)
  To: Rajendra Nayak, andy.gross, collinsd, mka, robh, ulf.hansson,
	viresh.kumar
  Cc: devicetree, linux-arm-msm, linux-kernel, Rajendra Nayak

Quoting Rajendra Nayak (2018-12-11 01:49:37)
> 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.
> 
> Suggested-by: Stephen Boyd <sboyd@kernel.org>
> Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
> ---

Reviewed-by: Stephen Boyd <swboyd@chromium.org>


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

* Re: [PATCH v6 10/10] soc: qcom: rpmhpd: Mark mx as a parent for cx
  2018-12-11 10:33     ` Rajendra Nayak
@ 2018-12-11 21:50       ` Stephen Boyd
  2018-12-12  4:13         ` Rajendra Nayak
  0 siblings, 1 reply; 27+ messages in thread
From: Stephen Boyd @ 2018-12-11 21:50 UTC (permalink / raw)
  To: Rajendra Nayak, Ulf Hansson
  Cc: Andy Gross, Rob Herring, Viresh Kumar, David Collins,
	Matthias Kaehlcke, DTML, linux-arm-msm,
	Linux Kernel Mailing List

Quoting Rajendra Nayak (2018-12-11 02:33:23)
> 
> 
> On 12/11/2018 3:52 PM, Ulf Hansson wrote:
> > On Tue, 11 Dec 2018 at 10:50, Rajendra Nayak <rnayak@codeaurora.org> wrote:
> >>
> >> 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.
> > 
> > I assume that also means the MX power domain must not be power off as
> > long as the CX power domain is powered on?
> 
> So with rpmh, there's really no separate on/off control, we just put
> it in the lowest perf state at off.

I think in theory the answer is MX can't be off if CX is on, but in
reality, MX and CX are never turned off, just set to something really
low and even then the constraint applies for MX >= CX. Is that right?

> 
> > 
> > Just to make sure there are no conflicting hierarchical constraints
> > between idle management and performance state management!?
> > 

I'm not sure what idle states mean to the CX and MX domains. Would it be
some sort of idle state governor attached at genpd creation time that
would adjust the main SoC power rails when all devices attached are
idle? Maybe I don't understand how idle states are different from
performance states.

My understanding is that devices using these domains would almost always
expect their clk frequency and clk on/off state to decide what the
performance state is, unless they need to ignore clk state because they
aren't managing clks and bump up the voltage directly when the device is
active. Either way, devices are actively managing the voltage they need
these voltage domains to operate at by using the genpd performance
states APIs.


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

* Re: [PATCH v6 00/10] Add power domain driver for corners on msm8996/sdm845
  2018-12-11  9:49 [PATCH v6 00/10] Add power domain driver for corners on msm8996/sdm845 Rajendra Nayak
                   ` (9 preceding siblings ...)
  2018-12-11  9:49 ` [PATCH v6 10/10] soc: qcom: rpmhpd: Mark mx as a parent for cx Rajendra Nayak
@ 2018-12-11 21:51 ` Stephen Boyd
  2018-12-12  4:17   ` Rajendra Nayak
  10 siblings, 1 reply; 27+ messages in thread
From: Stephen Boyd @ 2018-12-11 21:51 UTC (permalink / raw)
  To: Rajendra Nayak, andy.gross, collinsd, mka, robh, ulf.hansson,
	viresh.kumar
  Cc: devicetree, linux-arm-msm, linux-kernel, Rajendra Nayak

Quoting Rajendra Nayak (2018-12-11 01:49:28)
> 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

Is the idea that it can be squashed into the patches that use it by
reordering the series? But otherwise left at the end of the series to
make things simpler to merge without it?


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

* Re: [PATCH v6 03/10] soc: qcom: rpmpd: Add a Power domain driver to model corners
  2018-12-11  9:49 ` [PATCH v6 03/10] soc: qcom: rpmpd: Add a Power domain driver to model corners Rajendra Nayak
@ 2018-12-11 21:52   ` Stephen Boyd
  0 siblings, 0 replies; 27+ messages in thread
From: Stephen Boyd @ 2018-12-11 21:52 UTC (permalink / raw)
  To: Rajendra Nayak, andy.gross, collinsd, mka, robh, ulf.hansson,
	viresh.kumar
  Cc: devicetree, linux-arm-msm, linux-kernel, Rajendra Nayak

Quoting Rajendra Nayak (2018-12-11 01:49:31)
> 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.
> 
> Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
> Acked-by: Rob Herring <robh@kernel.org>
> ---

Reviewed-by: Stephen Boyd <swboyd@chromium.org>


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

* Re: [PATCH v6 05/10] arm64: dts: msm8996: Add rpmpd device node
  2018-12-11  9:49 ` [PATCH v6 05/10] arm64: dts: msm8996: Add rpmpd device node Rajendra Nayak
@ 2018-12-11 21:53   ` Stephen Boyd
  0 siblings, 0 replies; 27+ messages in thread
From: Stephen Boyd @ 2018-12-11 21:53 UTC (permalink / raw)
  To: Rajendra Nayak, andy.gross, collinsd, mka, robh, ulf.hansson,
	viresh.kumar
  Cc: devicetree, linux-arm-msm, linux-kernel, Rajendra Nayak

Quoting Rajendra Nayak (2018-12-11 01:49:33)
> Add rpmpd device node and its OPP table
> 
> Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
> ---

Reviewed-by: Stephen Boyd <swboyd@chromium.org>


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

* Re: [PATCH v6 06/10] soc: qcom: rpmhpd: Add RPMh power domain driver
  2018-12-11  9:49 ` [PATCH v6 06/10] soc: qcom: rpmhpd: Add RPMh power domain driver Rajendra Nayak
@ 2018-12-11 22:01   ` Stephen Boyd
  2018-12-12  5:04     ` Rajendra Nayak
  0 siblings, 1 reply; 27+ messages in thread
From: Stephen Boyd @ 2018-12-11 22:01 UTC (permalink / raw)
  To: Rajendra Nayak, andy.gross, collinsd, mka, robh, ulf.hansson,
	viresh.kumar
  Cc: devicetree, linux-arm-msm, linux-kernel, Rajendra Nayak

Quoting Rajendra Nayak (2018-12-11 01:49:34)
> 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

Why capitalize vote?

> 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

Can you tab these in?

> 
> 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
> 
> Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>

Just minor nitpicks ahead and a warning.

> diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
> index f1b25fdcf2ad..dd6ca92985ee 100644
> --- a/drivers/soc/qcom/Makefile
> +++ b/drivers/soc/qcom/Makefile
> @@ -22,3 +22,4 @@ 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
> +obj-$(CONFIG_QCOM_RPMHPD) += rpmhpd.o

Put this before RPMPD? At least it would be semi-sorted then.

> diff --git a/drivers/soc/qcom/rpmhpd.c b/drivers/soc/qcom/rpmhpd.c
> new file mode 100644
> index 000000000000..f993a86be48c
> --- /dev/null
> +++ b/drivers/soc/qcom/rpmhpd.c
> @@ -0,0 +1,417 @@
[..]
> +
> +static int rpmhpd_update_level_mapping(struct rpmhpd *rpmhpd)
> +{
> +       u8 buf[RPMH_ARC_MAX_LEVELS * RPMH_ARC_LEVEL_SIZE];
> +       int i, j, len, ret;
> +
> +       len = cmd_db_read_aux_data_len(rpmhpd->res_name);
> +       if (len <= 0)
> +               return len;
> +       else if (len > RPMH_ARC_MAX_LEVELS * RPMH_ARC_LEVEL_SIZE)
> +               return -EINVAL;
> +
> +       ret = cmd_db_read_aux_data(rpmhpd->res_name, buf, len);
> +       if (ret < 0)
> +               return ret;

I've changed cmd_db_read_aux_data() and that change is winding through
the arm-soc tree. This will break in the compilation phase in
linux-next.

> +
> +       rpmhpd->level_count = len / RPMH_ARC_LEVEL_SIZE;
> +
> +       for (i = 0; i < rpmhpd->level_count; i++) {
> +               rpmhpd->level[i] = 0;
> +               for (j = 0; j < RPMH_ARC_LEVEL_SIZE; j++)
> +                       rpmhpd->level[i] |=
> +                               buf[i * RPMH_ARC_LEVEL_SIZE + j] << (8 * j);
> +
> +               /*
> +                * The AUX data may be zero padded.  These 0 valued entries at
> +                * the end of the map must be ignored.
> +                */
> +               if (i > 0 && rpmhpd->level[i] == 0) {
> +                       rpmhpd->level_count = i;
> +                       break;
> +               }
> +               pr_debug("%s: ARC hlvl=%2d --> vlvl=%4u\n", rpmhpd->res_name, i,
> +                        rpmhpd->level[i]);
> +       }
> +
> +       return 0;
> +}
> +
> +static int rpmhpd_probe(struct platform_device *pdev)
> +{
> +       int i, ret;
> +       size_t num_pds;
> +       struct device *dev = &pdev->dev;
> +       struct genpd_onecell_data *data;
> +       struct rpmhpd **rpmhpds;
> +       const struct rpmhpd_desc *desc;
> +
> +       desc = of_device_get_match_data(dev);
> +       if (!desc)
> +               return -EINVAL;
> +
> +       rpmhpds = desc->rpmhpds;
> +       num_pds = desc->num_pds;
> +
> +       data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
> +       if (!data)
> +               return -ENOMEM;
> +
> +       data->domains = devm_kcalloc(dev, num_pds, sizeof(*data->domains),
> +                                    GFP_KERNEL);
> +       if (!data->domains)
> +               return -ENOMEM;
> +
> +       data->num_domains = num_pds;
> +
> +       ret = cmd_db_ready();

Does this matter? I thought we forced cmd_db_ready() in the rpmh driver
probe, and that was the parent of all rpmh devices so we should be fine
to not need to check it again here?

> +       if (ret) {
> +               if (ret != -EPROBE_DEFER)
> +                       dev_err(dev, "Command DB unavailable, ret=%d\n", ret);
> +               return ret;
> +       }
> +

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

* Re: [PATCH v6 07/10] arm64: dts: sdm845: Add rpmh powercontroller node
  2018-12-11  9:49 ` [PATCH v6 07/10] arm64: dts: sdm845: Add rpmh powercontroller node Rajendra Nayak
@ 2018-12-11 22:01   ` Stephen Boyd
  0 siblings, 0 replies; 27+ messages in thread
From: Stephen Boyd @ 2018-12-11 22:01 UTC (permalink / raw)
  To: Rajendra Nayak, andy.gross, collinsd, mka, robh, ulf.hansson,
	viresh.kumar
  Cc: devicetree, linux-arm-msm, linux-kernel, Rajendra Nayak

Quoting Rajendra Nayak (2018-12-11 01:49:35)
> Add the DT node for the rpmhpd powercontroller.
> 
> Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
> Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---

Reviewed-by: Stephen Boyd <swboyd@chromium.org>


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

* Re: [PATCH v6 10/10] soc: qcom: rpmhpd: Mark mx as a parent for cx
  2018-12-11 21:50       ` Stephen Boyd
@ 2018-12-12  4:13         ` Rajendra Nayak
  2018-12-12 18:32           ` Stephen Boyd
  0 siblings, 1 reply; 27+ messages in thread
From: Rajendra Nayak @ 2018-12-12  4:13 UTC (permalink / raw)
  To: Stephen Boyd, Ulf Hansson
  Cc: Andy Gross, Rob Herring, Viresh Kumar, David Collins,
	Matthias Kaehlcke, DTML, linux-arm-msm,
	Linux Kernel Mailing List


[]...

>>>> 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.
>>>
>>> I assume that also means the MX power domain must not be power off as
>>> long as the CX power domain is powered on?
>>
>> So with rpmh, there's really no separate on/off control, we just put
>> it in the lowest perf state at off.
> 
> I think in theory the answer is MX can't be off if CX is on, but in
> reality, MX and CX are never turned off, just set to something really
> low and even then the constraint applies for MX >= CX. Is that right?

to some extent, let me clarify this a bit more. rpmh is the central entity
controlling these rails and takes a final call on when it can or cannot
be 'really' off and when its turned on, at what level it should be set to.

CPU is just one of the entities 'voting' on them. Now legacy platforms which
had rpm (like msm8996) did have separate control to send a
on/off vote and a performance level vote. With rpmh, its just that there
is no separate message that you send to rpmh for OFF, its just mapped to
the lowest perf level. So think of it as the lowest perf level is mapped to
a '0' which is same as OFF.

So when you say 'MX can't be off if CX is on', yes MX can't be at the lowest
level '0', while CX is at something higher.

>>> Just to make sure there are no conflicting hierarchical constraints
>>> between idle management and performance state management!?
>>>
> 
> I'm not sure what idle states mean to the CX and MX domains. Would it be
> some sort of idle state governor attached at genpd creation time that
> would adjust the main SoC power rails when all devices attached are
> idle? Maybe I don't understand how idle states are different from
> performance states.
> My understanding is that devices using these domains would almost always
> expect their clk frequency and clk on/off state to decide what the
> performance state is, unless they need to ignore clk state because they
> aren't managing clks and bump up the voltage directly when the device is
> active. Either way, devices are actively managing the voltage they need
> these voltage domains to operate at by using the genpd performance
> states APIs.

I am not quite sure whats the point that you are trying to make here,
but this is what I would expect the users of these genpds to do,
regardless of if they have a clk dependency or not.
When the device is active, vote for a performance state they need
then request for the genpd to be on. When they are idle, request for the
genpd to be turned off.
  

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

* Re: [PATCH v6 00/10] Add power domain driver for corners on msm8996/sdm845
  2018-12-11 21:51 ` [PATCH v6 00/10] Add power domain driver for corners on msm8996/sdm845 Stephen Boyd
@ 2018-12-12  4:17   ` Rajendra Nayak
  0 siblings, 0 replies; 27+ messages in thread
From: Rajendra Nayak @ 2018-12-12  4:17 UTC (permalink / raw)
  To: Stephen Boyd, andy.gross, collinsd, mka, robh, ulf.hansson, viresh.kumar
  Cc: devicetree, linux-arm-msm, linux-kernel


On 12/12/2018 3:21 AM, Stephen Boyd wrote:
> Quoting Rajendra Nayak (2018-12-11 01:49:28)
>> 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
> 
> Is the idea that it can be squashed into the patches that use it by
> reordering the series? But otherwise left at the end of the series to
> make things simpler to merge without it?

Yes, I left them at the end so its easier to merge. The PM domains change
would need to go via Ulf/Viresh while the SoC drivers using them would
go via Andy. So now its only 09/10 that's dependent on 08/10 and not the
entire series.


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

* Re: [PATCH v6 06/10] soc: qcom: rpmhpd: Add RPMh power domain driver
  2018-12-11 22:01   ` Stephen Boyd
@ 2018-12-12  5:04     ` Rajendra Nayak
  0 siblings, 0 replies; 27+ messages in thread
From: Rajendra Nayak @ 2018-12-12  5:04 UTC (permalink / raw)
  To: Stephen Boyd, andy.gross, collinsd, mka, robh, ulf.hansson, viresh.kumar
  Cc: devicetree, linux-arm-msm, linux-kernel


On 12/12/2018 3:31 AM, Stephen Boyd wrote:
> Quoting Rajendra Nayak (2018-12-11 01:49:34)
>> 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
> 
> Why capitalize vote?

will fix,

> 
>> 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
> 
> Can you tab these in?

sure, will do

> 
>>
>> 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
>>
>> Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
>> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
> 
> Just minor nitpicks ahead and a warning.
> 
>> diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
>> index f1b25fdcf2ad..dd6ca92985ee 100644
>> --- a/drivers/soc/qcom/Makefile
>> +++ b/drivers/soc/qcom/Makefile
>> @@ -22,3 +22,4 @@ 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
>> +obj-$(CONFIG_QCOM_RPMHPD) += rpmhpd.o
> 
> Put this before RPMPD? At least it would be semi-sorted then.

okay, will do

> 
>> diff --git a/drivers/soc/qcom/rpmhpd.c b/drivers/soc/qcom/rpmhpd.c
>> new file mode 100644
>> index 000000000000..f993a86be48c
>> --- /dev/null
>> +++ b/drivers/soc/qcom/rpmhpd.c
>> @@ -0,0 +1,417 @@
> [..]
>> +
>> +static int rpmhpd_update_level_mapping(struct rpmhpd *rpmhpd)
>> +{
>> +       u8 buf[RPMH_ARC_MAX_LEVELS * RPMH_ARC_LEVEL_SIZE];
>> +       int i, j, len, ret;
>> +
>> +       len = cmd_db_read_aux_data_len(rpmhpd->res_name);
>> +       if (len <= 0)
>> +               return len;
>> +       else if (len > RPMH_ARC_MAX_LEVELS * RPMH_ARC_LEVEL_SIZE)
>> +               return -EINVAL;
>> +
>> +       ret = cmd_db_read_aux_data(rpmhpd->res_name, buf, len);
>> +       if (ret < 0)
>> +               return ret;
> 
> I've changed cmd_db_read_aux_data() and that change is winding through
> the arm-soc tree. This will break in the compilation phase in
> linux-next.

will resend these based on Andy's for-next

> 
>> +
>> +       rpmhpd->level_count = len / RPMH_ARC_LEVEL_SIZE;
>> +
>> +       for (i = 0; i < rpmhpd->level_count; i++) {
>> +               rpmhpd->level[i] = 0;
>> +               for (j = 0; j < RPMH_ARC_LEVEL_SIZE; j++)
>> +                       rpmhpd->level[i] |=
>> +                               buf[i * RPMH_ARC_LEVEL_SIZE + j] << (8 * j);
>> +
>> +               /*
>> +                * The AUX data may be zero padded.  These 0 valued entries at
>> +                * the end of the map must be ignored.
>> +                */
>> +               if (i > 0 && rpmhpd->level[i] == 0) {
>> +                       rpmhpd->level_count = i;
>> +                       break;
>> +               }
>> +               pr_debug("%s: ARC hlvl=%2d --> vlvl=%4u\n", rpmhpd->res_name, i,
>> +                        rpmhpd->level[i]);
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static int rpmhpd_probe(struct platform_device *pdev)
>> +{
>> +       int i, ret;
>> +       size_t num_pds;
>> +       struct device *dev = &pdev->dev;
>> +       struct genpd_onecell_data *data;
>> +       struct rpmhpd **rpmhpds;
>> +       const struct rpmhpd_desc *desc;
>> +
>> +       desc = of_device_get_match_data(dev);
>> +       if (!desc)
>> +               return -EINVAL;
>> +
>> +       rpmhpds = desc->rpmhpds;
>> +       num_pds = desc->num_pds;
>> +
>> +       data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
>> +       if (!data)
>> +               return -ENOMEM;
>> +
>> +       data->domains = devm_kcalloc(dev, num_pds, sizeof(*data->domains),
>> +                                    GFP_KERNEL);
>> +       if (!data->domains)
>> +               return -ENOMEM;
>> +
>> +       data->num_domains = num_pds;
>> +
>> +       ret = cmd_db_ready();
> 
> Does this matter? I thought we forced cmd_db_ready() in the rpmh driver
> probe, and that was the parent of all rpmh devices so we should be fine
> to not need to check it again here?

sure, will remove.

thanks for the review.

> 
>> +       if (ret) {
>> +               if (ret != -EPROBE_DEFER)
>> +                       dev_err(dev, "Command DB unavailable, ret=%d\n", ret);
>> +               return ret;
>> +       }
>> +

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

* Re: [PATCH v6 10/10] soc: qcom: rpmhpd: Mark mx as a parent for cx
  2018-12-12  4:13         ` Rajendra Nayak
@ 2018-12-12 18:32           ` Stephen Boyd
  2018-12-13 16:02             ` Ulf Hansson
  0 siblings, 1 reply; 27+ messages in thread
From: Stephen Boyd @ 2018-12-12 18:32 UTC (permalink / raw)
  To: Rajendra Nayak, Ulf Hansson
  Cc: Andy Gross, Rob Herring, Viresh Kumar, David Collins,
	Matthias Kaehlcke, DTML, linux-arm-msm,
	Linux Kernel Mailing List

Quoting Rajendra Nayak (2018-12-11 20:13:13)
> 
> >>> Just to make sure there are no conflicting hierarchical constraints
> >>> between idle management and performance state management!?
> >>>
> > 
> > I'm not sure what idle states mean to the CX and MX domains. Would it be
> > some sort of idle state governor attached at genpd creation time that
> > would adjust the main SoC power rails when all devices attached are
> > idle? Maybe I don't understand how idle states are different from
> > performance states.
> > My understanding is that devices using these domains would almost always
> > expect their clk frequency and clk on/off state to decide what the
> > performance state is, unless they need to ignore clk state because they
> > aren't managing clks and bump up the voltage directly when the device is
> > active. Either way, devices are actively managing the voltage they need
> > these voltage domains to operate at by using the genpd performance
> > states APIs.
> 
> I am not quite sure whats the point that you are trying to make here,
> but this is what I would expect the users of these genpds to do,
> regardless of if they have a clk dependency or not.
> When the device is active, vote for a performance state they need
> then request for the genpd to be on. When they are idle, request for the
> genpd to be turned off.
>   

I believe Ulf is asking because he's proposing to make genpd idle states
and genpd performance states orthogonal to each other. And to also make
performance states unaffected by the on/off state of the genpd.


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

* Re: [PATCH v6 10/10] soc: qcom: rpmhpd: Mark mx as a parent for cx
  2018-12-12 18:32           ` Stephen Boyd
@ 2018-12-13 16:02             ` Ulf Hansson
  0 siblings, 0 replies; 27+ messages in thread
From: Ulf Hansson @ 2018-12-13 16:02 UTC (permalink / raw)
  To: swboyd, Rajendra Nayak
  Cc: Andy Gross, Rob Herring, Viresh Kumar, David Collins,
	Matthias Kaehlcke, DTML, linux-arm-msm,
	Linux Kernel Mailing List

On Wed, 12 Dec 2018 at 19:32, Stephen Boyd <swboyd@chromium.org> wrote:
>
> Quoting Rajendra Nayak (2018-12-11 20:13:13)
> >
> > >>> Just to make sure there are no conflicting hierarchical constraints
> > >>> between idle management and performance state management!?
> > >>>
> > >
> > > I'm not sure what idle states mean to the CX and MX domains. Would it be
> > > some sort of idle state governor attached at genpd creation time that
> > > would adjust the main SoC power rails when all devices attached are
> > > idle? Maybe I don't understand how idle states are different from
> > > performance states.
> > > My understanding is that devices using these domains would almost always
> > > expect their clk frequency and clk on/off state to decide what the
> > > performance state is, unless they need to ignore clk state because they
> > > aren't managing clks and bump up the voltage directly when the device is
> > > active. Either way, devices are actively managing the voltage they need
> > > these voltage domains to operate at by using the genpd performance
> > > states APIs.
> >
> > I am not quite sure whats the point that you are trying to make here,
> > but this is what I would expect the users of these genpds to do,
> > regardless of if they have a clk dependency or not.
> > When the device is active, vote for a performance state they need
> > then request for the genpd to be on. When they are idle, request for the
> > genpd to be turned off.
> >
>
> I believe Ulf is asking because he's proposing to make genpd idle states
> and genpd performance states orthogonal to each other. And to also make
> performance states unaffected by the on/off state of the genpd.

Yes, that's one of the reasons.

Anyway, I appreciate both of yours descriptive feedback, no further
worries from my side!

Kind regards
Uffe

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

end of thread, other threads:[~2018-12-13 16:03 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-12-11  9:49 [PATCH v6 00/10] Add power domain driver for corners on msm8996/sdm845 Rajendra Nayak
2018-12-11  9:49 ` [PATCH v6 01/10] dt-bindings: opp: Introduce qcom-opp bindings Rajendra Nayak
2018-12-11  9:49 ` [PATCH v6 02/10] dt-bindings: power: Add qcom rpm power domain driver bindings Rajendra Nayak
2018-12-11 21:28   ` Stephen Boyd
2018-12-11  9:49 ` [PATCH v6 03/10] soc: qcom: rpmpd: Add a Power domain driver to model corners Rajendra Nayak
2018-12-11 21:52   ` Stephen Boyd
2018-12-11  9:49 ` [PATCH v6 04/10] soc: qcom: rpmpd: Add support for get/set performance state Rajendra Nayak
2018-12-11  9:49 ` [PATCH v6 05/10] arm64: dts: msm8996: Add rpmpd device node Rajendra Nayak
2018-12-11 21:53   ` Stephen Boyd
2018-12-11  9:49 ` [PATCH v6 06/10] soc: qcom: rpmhpd: Add RPMh power domain driver Rajendra Nayak
2018-12-11 22:01   ` Stephen Boyd
2018-12-12  5:04     ` Rajendra Nayak
2018-12-11  9:49 ` [PATCH v6 07/10] arm64: dts: sdm845: Add rpmh powercontroller node Rajendra Nayak
2018-12-11 22:01   ` Stephen Boyd
2018-12-11  9:49 ` [PATCH v6 08/10] PM / Domains: Add a simple_opp_to_performance_state() helper Rajendra Nayak
2018-12-11 21:33   ` Stephen Boyd
2018-12-11  9:49 ` [PATCH v6 09/10] soc: qcom: rpmpd: Use " Rajendra Nayak
2018-12-11 21:34   ` Stephen Boyd
2018-12-11  9:49 ` [PATCH v6 10/10] soc: qcom: rpmhpd: Mark mx as a parent for cx Rajendra Nayak
2018-12-11 10:22   ` Ulf Hansson
2018-12-11 10:33     ` Rajendra Nayak
2018-12-11 21:50       ` Stephen Boyd
2018-12-12  4:13         ` Rajendra Nayak
2018-12-12 18:32           ` Stephen Boyd
2018-12-13 16:02             ` Ulf Hansson
2018-12-11 21:51 ` [PATCH v6 00/10] Add power domain driver for corners on msm8996/sdm845 Stephen Boyd
2018-12-12  4:17   ` Rajendra Nayak

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).