All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] Support dynamic voltage frequency scaling inside clock controller
@ 2022-08-05  7:49 Jun Nie
  2022-08-05  7:49 ` [PATCH 1/4] clk: Aggregate power operation in " Jun Nie
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: Jun Nie @ 2022-08-05  7:49 UTC (permalink / raw)
  To: abel.vesa, bjorn.andersson, mturquette, sboyd
  Cc: agross, shawn.guo, bryan.odonoghue, linux-clk, linux-arm-msm,
	devicetree, Jun Nie

Support dynamic voltage frequency scaling inside clock controller with
changes in clock framework. And added msm8916 as the first SoC to
support this feature.

Jun Nie (4):
  clk: Aggregate power operation in clock controller
  soc: qcom: rpmpd: Add corner power-domains states
  arm64: dts: qcom: add power domain for clk controller
  clk: qcom: gcc-msm8916: Add power domain data

 arch/arm64/boot/dts/qcom/msm8916.dtsi  |  14 +-
 drivers/clk/clk.c                      | 212 ++++++++++++++++++++++++-
 drivers/clk/qcom/gcc-msm8916.c         | 182 +++++++++++++++++++++
 include/dt-bindings/power/qcom-rpmpd.h |   8 +
 include/linux/clk-provider.h           |  62 ++++++++
 5 files changed, 470 insertions(+), 8 deletions(-)

-- 
2.25.1


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

* [PATCH 1/4] clk: Aggregate power operation in clock controller
  2022-08-05  7:49 [PATCH 0/4] Support dynamic voltage frequency scaling inside clock controller Jun Nie
@ 2022-08-05  7:49 ` Jun Nie
  2022-08-05  7:49 ` [PATCH 2/4] soc: qcom: rpmpd: Add corner power-domains states Jun Nie
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: Jun Nie @ 2022-08-05  7:49 UTC (permalink / raw)
  To: abel.vesa, bjorn.andersson, mturquette, sboyd
  Cc: agross, shawn.guo, bryan.odonoghue, linux-clk, linux-arm-msm,
	devicetree, Jun Nie

Add power domain operation per clk frequency. Some hardware support
dynamic voltage frequency scaling in clock controller besides devices.
Which is not related to any clock consumer devices. While power domain
operation is operated per device in driver model. If they are voted per
clk, not per device, we need to aggregate them in clock framework,
then send request to power framework.

Signed-off-by: Jun Nie <jun.nie@linaro.org>
---
 drivers/clk/clk.c            | 212 ++++++++++++++++++++++++++++++++++-
 include/linux/clk-provider.h |  62 ++++++++++
 2 files changed, 272 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index f00d4c1158d7..0ab79b9ebefd 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -18,6 +18,7 @@
 #include <linux/of.h>
 #include <linux/device.h>
 #include <linux/init.h>
+#include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
 #include <linux/sched.h>
 #include <linux/clkdev.h>
@@ -89,6 +90,7 @@ struct clk_core {
 	struct hlist_node	debug_node;
 #endif
 	struct kref		ref;
+	struct clk_power_data	*power;
 };
 
 #define CREATE_TRACE_POINTS
@@ -812,6 +814,161 @@ int clk_rate_exclusive_get(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(clk_rate_exclusive_get);
 
+static void clk_unvote_genpd(struct clk_core *core)
+{
+	struct clkpstate_node *ps_node = NULL;
+	struct clk_power_data *power = core->power;
+	unsigned int pstate = 0;
+
+	mutex_lock(power->genpd_lock);
+	/* Do not free the node. As performance states number is limited, and we
+	 * will re-visit it later.
+	 */
+	list_del_init(&power->genpd_list);
+	power->genpd_pstate = 0;
+
+	/* Find and set the highest pstate */
+	list_for_each_entry_reverse(ps_node, power->genpd_head, genpd_list) {
+		if (!list_empty(&ps_node->genpd_pstate_head)) {
+			pstate = ps_node->pstate;
+			break;
+		}
+	}
+
+	pr_debug("%s: clk %s unvote genpd set genpd perf state %d\n",
+		 __func__, core->name, pstate);
+	dev_pm_genpd_set_performance_state(*power->genpd_dev, pstate);
+
+	mutex_unlock(power->genpd_lock);
+}
+
+static int clk_vote_genpd(struct clk_core *core, unsigned long rate)
+{
+	struct clkpstate_node *new_ps_node, *ps_node, *pre_ps_node = NULL;
+	unsigned int cnt, pstate = 0;
+	struct list_head *insert_pos;
+	int ret = 0;
+	struct clk_power_data *power = core->power;
+	const struct genpdopp_table *tbl = power->genpdopp_table;
+
+	/* Find opp pstate for required rate */
+	for (cnt = 0; cnt < power->genpdopp_num; cnt++, tbl++) {
+		if (rate <= tbl->ceiling_rate) {
+			pstate = tbl->pstate;
+			break;
+		}
+	}
+
+	if (!pstate && cnt == power->genpdopp_num) {
+		pr_err("%s: clk %s rate %lu not supported by genpd\n", __func__,
+			core->name, rate);
+		return -EINVAL;
+	}
+
+	pr_debug("%s: clk %s votes perf state %d\n",
+		 __func__, core->name, pstate);
+	mutex_lock(power->genpd_lock);
+	if (list_empty(power->genpd_head)) {
+		insert_pos = power->genpd_head;
+		goto new_pstate_node;
+	}
+
+	/* If this clk power is already in some perf state */
+	if (!list_empty(&power->genpd_list)) {
+		if (pstate == power->genpd_pstate) {
+			mutex_unlock(power->genpd_lock);
+			return 0;
+		}
+		list_del_init(&power->genpd_list);
+	}
+
+	/* search the genpd pstate node that match pstate requirement */
+	list_for_each_entry(ps_node, power->genpd_head, genpd_list) {
+		if (ps_node->pstate == pstate) {
+			new_ps_node = ps_node;
+			list_add(&power->genpd_list,
+				 &new_ps_node->genpd_pstate_head);
+			goto linked_into_pstate;
+		}
+		if (ps_node->pstate > pstate) {
+			if (pre_ps_node != NULL)
+				insert_pos = &pre_ps_node->genpd_list;
+			else
+				insert_pos = power->genpd_head;
+			goto new_pstate_node;
+		}
+		pre_ps_node = ps_node;
+	}
+	/* Add new genpd pstate node in the end */
+	insert_pos = &pre_ps_node->genpd_list;
+
+new_pstate_node:
+	new_ps_node = kmalloc(sizeof(struct clkpstate_node), GFP_KERNEL);
+	if (new_ps_node == NULL) {
+		mutex_unlock(power->genpd_lock);
+		return -ENOMEM;
+	}
+
+	/* link this pstate node into genpd pstate link list */
+	INIT_LIST_HEAD(&new_ps_node->genpd_list);
+	INIT_LIST_HEAD(&new_ps_node->genpd_pstate_head);
+	new_ps_node->pstate = pstate;
+	list_add(&new_ps_node->genpd_list, insert_pos);
+	list_add(&power->genpd_list, &new_ps_node->genpd_pstate_head);
+
+	/* Find and set the highest pstate */
+	list_for_each_entry_reverse(ps_node, power->genpd_head, genpd_list) {
+		if (!list_empty(&ps_node->genpd_pstate_head)) {
+			pr_debug("%s: genpd set perf state %d for clk %s\n",
+				  __func__, pstate, core->name);
+			ret = dev_pm_genpd_set_performance_state(
+					*power->genpd_dev, ps_node->pstate);
+			if (ret) {
+				/* No need to free new_ps_node as it's empty */
+				mutex_unlock(power->genpd_lock);
+				pr_err("%s: fail to set genpd opp for clk %s\n",
+					__func__, core->name);
+				return ret;
+			}
+			break;
+		}
+	}
+
+linked_into_pstate:
+	power->genpd_pstate = pstate;
+	mutex_unlock(power->genpd_lock);
+	return ret;
+}
+
+static void clk_unvote_power(struct clk_core *core)
+{
+	struct clk_power_data *power = core->power;
+
+	if (!core->power)
+		return;
+
+	/* regulator added here in future */
+
+	if (power->genpd_dev)
+		clk_unvote_genpd(core);
+}
+
+static int clk_vote_power(struct clk_core *core, unsigned long rate)
+{
+	struct clk_power_data *power = core->power;
+	int ret = 0;
+
+	if (!core->power)
+		return 0;
+
+	/* regulator added here in future */
+
+	if (power->genpd_dev)
+		ret = clk_vote_genpd(core, rate);
+
+	return ret;
+}
+
 static void clk_core_unprepare(struct clk_core *core)
 {
 	lockdep_assert_held(&prepare_lock);
@@ -840,6 +997,8 @@ static void clk_core_unprepare(struct clk_core *core)
 	if (core->ops->unprepare)
 		core->ops->unprepare(core->hw);
 
+	clk_unvote_power(core);
+
 	clk_pm_runtime_put(core);
 
 	trace_clk_unprepare_complete(core);
@@ -887,6 +1046,10 @@ static int clk_core_prepare(struct clk_core *core)
 		if (ret)
 			return ret;
 
+		ret = clk_vote_power(core, core->rate);
+		if (ret)
+			return ret;
+
 		ret = clk_core_prepare(core->parent);
 		if (ret)
 			goto runtime_put;
@@ -2189,7 +2352,7 @@ static int clk_core_set_rate_nolock(struct clk_core *core,
 {
 	struct clk_core *top, *fail_clk;
 	unsigned long rate;
-	int ret = 0;
+	int ret = 0, post_set_power = 0;
 
 	if (!core)
 		return 0;
@@ -2223,10 +2386,21 @@ static int clk_core_set_rate_nolock(struct clk_core *core,
 		goto err;
 	}
 
+	if (rate > core->rate) {
+		ret = clk_vote_power(core, rate);
+		if (ret)
+			goto err;
+	} else {
+		post_set_power = 1;
+	}
+
 	/* change the rates */
 	clk_change_rate(top);
 
 	core->req_rate = req_rate;
+
+	if (post_set_power)
+		ret = clk_vote_power(core, rate);
 err:
 	clk_pm_runtime_put(core);
 
@@ -3905,7 +4079,8 @@ static void clk_core_free_parent_map(struct clk_core *core)
 static struct clk *
 __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
 {
-	int ret;
+	int ret, cnt;
+	unsigned long rate;
 	struct clk_core *core;
 	const struct clk_init_data *init = hw->init;
 
@@ -3946,6 +4121,38 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
 	core->min_rate = 0;
 	core->max_rate = ULONG_MAX;
 
+	if (init->power && init->power_magic == CLK_POWER_MAGIC) {
+		struct clk_power_data *power = init->power;
+		const struct genpdopp_table *ptable = power->genpdopp_table;
+
+		power->core = core;
+		if (power->genpd_dev) {
+			if (!power->genpd_lock || !power->genpd_head ||
+			   !power->genpdopp_table || !power->genpdopp_num) {
+				pr_err("%s: invalid power domain for clk %s\n",
+					__func__, core->name);
+				goto skip_clk_power;
+			}
+		}
+		for (cnt = 0; cnt < power->genpdopp_num - 1; cnt++) {
+			rate = ptable->ceiling_rate;
+			ptable++;
+			if (rate >= ptable->ceiling_rate) {
+				pr_err("%s: invalid asending rate for clk %s\n",
+					__func__, core->name);
+				ret = -EINVAL;
+				goto skip_clk_power;
+			}
+		}
+		core->power = kmalloc(sizeof(*power), GFP_KERNEL);
+		if (!core->power)
+			goto skip_clk_power;
+
+		memcpy(core->power, power, sizeof(*power));
+		INIT_LIST_HEAD(&core->power->genpd_list);
+	}
+
+skip_clk_power:
 	ret = clk_core_populate_parent_map(core, init);
 	if (ret)
 		goto fail_parents;
@@ -3978,6 +4185,7 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
 fail_create_clk:
 	clk_core_free_parent_map(core);
 fail_parents:
+	kfree(core->power);
 fail_ops:
 	kfree_const(core->name);
 fail_name:
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index c10dc4c659e2..bcf62fb0a6a1 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -268,12 +268,71 @@ struct clk_parent_data {
 	int			index;
 };
 
+/**
+ * struct genpdopp_table - opp pstate and clk rate mapping table
+ *
+ * @pstate: power domain performance state
+ * @ceiling_rate: the max clock rate this pstate supports
+ */
+struct genpdopp_table {
+	unsigned int	pstate;
+	unsigned long	ceiling_rate;
+};
+
+/**
+ * struct clkpstate_node - opp pstate node holds lists of clks that depends
+ *			on a specific performance state. The nodes should be
+ *			from low to high pstate lead by genpd_head.
+ *
+ * @genpd_list: list node that linked to a genpd list
+ * @genpd_pstate_head: list head that lead clks that depends on this pstate
+ * @pstate: power domain performance state
+ */
+struct clkpstate_node {
+	struct list_head	genpd_list;
+	struct list_head	genpd_pstate_head;
+	unsigned int		pstate;
+};
+
+/**
+ * struct clk_power_data - holds power data that's common to all clocks and is
+ * shared between the clock provider and the common clock framework.
+ *
+ * @genpd_list: genpd consumer node of this clk, to be into one of genpd pstate
+ *		consumer lists that lead by genpd_head when clk rate is set to
+ *		a genpd opp pstate.
+ * @genpd_head: list head that holds genpd performance states heads, where
+ *		genpd performance list heads are held. Those heads are holding
+ *		genpd consumers in different opp pstate.
+ * @genpd_lock: spin_lock that protect genpd list operation
+ * @genpd_dev: device that bind the power domain where clk is on. It is clock
+ *		controller device by default, or virtual device if there are
+ *		multiple power domain for controller device
+ * @genpdopp_table: genpd opp pstate and clk rate mapping table. The rate should
+		be listed from lowest to highest strictly in table.
+ * @genpdopp_num: genpd opp pstate table entry number
+ * @genpd_pstate: current genpd opp pstate this clk requires
+ */
+struct clk_power_data {
+	struct list_head		genpd_list;
+	struct list_head		*genpd_head;
+	struct mutex			*genpd_lock;
+	struct device			**genpd_dev;
+	const struct genpdopp_table	*genpdopp_table;
+	unsigned int			genpdopp_num;
+	unsigned int			genpd_pstate;
+	struct clk_core			*core;
+};
+
 /**
  * struct clk_init_data - holds init data that's common to all clocks and is
  * shared between the clock provider and the common clock framework.
  *
  * @name: clock name
  * @ops: operations this clock supports
+ * power: power data that this clock operates on
+ * @power_magic: magic number to indicate that power data is valid. To sanity
+ *	check for none NULL invalid power data case.
  * @parent_names: array of string names for all possible parents
  * @parent_data: array of parent data for all possible parents (when some
  *               parents are external to the clk controller)
@@ -282,9 +341,12 @@ struct clk_parent_data {
  * @num_parents: number of possible parents
  * @flags: framework-level hints and quirks
  */
+#define CLK_POWER_MAGIC 0x5c5c6969
 struct clk_init_data {
 	const char		*name;
+	int			power_magic;
 	const struct clk_ops	*ops;
+	struct clk_power_data	*power;
 	/* Only one of the following three should be assigned */
 	const char		* const *parent_names;
 	const struct clk_parent_data	*parent_data;
-- 
2.25.1


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

* [PATCH 2/4] soc: qcom: rpmpd: Add corner power-domains states
  2022-08-05  7:49 [PATCH 0/4] Support dynamic voltage frequency scaling inside clock controller Jun Nie
  2022-08-05  7:49 ` [PATCH 1/4] clk: Aggregate power operation in " Jun Nie
@ 2022-08-05  7:49 ` Jun Nie
  2022-09-26 16:29   ` Bjorn Andersson
  2022-08-05  7:49 ` [PATCH 3/4] arm64: dts: qcom: add power domain for clk controller Jun Nie
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 10+ messages in thread
From: Jun Nie @ 2022-08-05  7:49 UTC (permalink / raw)
  To: abel.vesa, bjorn.andersson, mturquette, sboyd
  Cc: agross, shawn.guo, bryan.odonoghue, linux-clk, linux-arm-msm,
	devicetree, Jun Nie

Some SoCs use corner instead of level in rpm regulator, such as
MSM8916 and MSM8939. Add these power-domains states value so that
devices can vote them.

Note that there is a shift with 1 when converting the value from
regulator usage in Qualcomm Linux 3.18 to power domain usage here.
Because corner is not well hacked in regulator framework in 3.18.
For example, RPM_REGULATOR_CORNER_RETENTION is 2 in 3.18 while
RPM_SMD_CORNER_RETENTION is 1.

Signed-off-by: Jun Nie <jun.nie@linaro.org>
---
 include/dt-bindings/power/qcom-rpmpd.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/include/dt-bindings/power/qcom-rpmpd.h b/include/dt-bindings/power/qcom-rpmpd.h
index 6cce5b7aa940..f778dbbf083d 100644
--- a/include/dt-bindings/power/qcom-rpmpd.h
+++ b/include/dt-bindings/power/qcom-rpmpd.h
@@ -297,4 +297,12 @@
 #define RPM_SMD_LEVEL_TURBO_HIGH      448
 #define RPM_SMD_LEVEL_BINNING         512
 
+/* RPM SMD Power Domain performance levels in regulator corner method */
+#define RPM_SMD_CORNER_RETENTION	1
+#define RPM_SMD_CORNER_SVS_KRAIT	2
+#define RPM_SMD_CORNER_SVS_SOC		3
+#define RPM_SMD_CORNER_NORMAL		4
+#define RPM_SMD_CORNER_TURBO		5
+#define RPM_SMD_CORNER_SUPER_TURBO	6
+
 #endif
-- 
2.25.1


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

* [PATCH 3/4] arm64: dts: qcom: add power domain for clk controller
  2022-08-05  7:49 [PATCH 0/4] Support dynamic voltage frequency scaling inside clock controller Jun Nie
  2022-08-05  7:49 ` [PATCH 1/4] clk: Aggregate power operation in " Jun Nie
  2022-08-05  7:49 ` [PATCH 2/4] soc: qcom: rpmpd: Add corner power-domains states Jun Nie
@ 2022-08-05  7:49 ` Jun Nie
  2022-09-26 16:33   ` Bjorn Andersson
  2022-08-05  7:49 ` [PATCH 4/4] clk: qcom: gcc-msm8916: Add power domain data Jun Nie
  2022-08-05  9:32 ` [PATCH 0/4] Support dynamic voltage frequency scaling inside clock controller Stephan Gerhold
  4 siblings, 1 reply; 10+ messages in thread
From: Jun Nie @ 2022-08-05  7:49 UTC (permalink / raw)
  To: abel.vesa, bjorn.andersson, mturquette, sboyd
  Cc: agross, shawn.guo, bryan.odonoghue, linux-clk, linux-arm-msm,
	devicetree, Jun Nie

Add RPM power domain for clk controller so that clock controller can
use it for dynamic voltage frequency scaling.

Also replace the RPM power domain value with defninition.

Signed-off-by: Jun Nie <jun.nie@linaro.org>
---
 arch/arm64/boot/dts/qcom/msm8916.dtsi | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
index 05472510e29d..fdb32b3a23e8 100644
--- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
@@ -312,22 +312,22 @@ rpmpd_opp_table: opp-table {
 						compatible = "operating-points-v2";
 
 						rpmpd_opp_ret: opp1 {
-							opp-level = <1>;
+							opp-level = <RPM_SMD_CORNER_RETENTION>;
 						};
 						rpmpd_opp_svs_krait: opp2 {
-							opp-level = <2>;
+							opp-level = <RPM_SMD_CORNER_SVS_KRAIT>;
 						};
 						rpmpd_opp_svs_soc: opp3 {
-							opp-level = <3>;
+							opp-level = <RPM_SMD_CORNER_SVS_SOC>;
 						};
 						rpmpd_opp_nom: opp4 {
-							opp-level = <4>;
+							opp-level = <RPM_SMD_CORNER_NORMAL>;
 						};
 						rpmpd_opp_turbo: opp5 {
-							opp-level = <5>;
+							opp-level = <RPM_SMD_CORNER_TURBO>;
 						};
 						rpmpd_opp_super_turbo: opp6 {
-							opp-level = <6>;
+							opp-level = <RPM_SMD_CORNER_SUPER_TURBO>;
 						};
 					};
 				};
@@ -933,6 +933,8 @@ gcc: clock-controller@1800000 {
 			#clock-cells = <1>;
 			#reset-cells = <1>;
 			#power-domain-cells = <1>;
+			power-domains = <&rpmpd MSM8916_VDDCX>;
+			power-domain-names = "vdd";
 			reg = <0x01800000 0x80000>;
 		};
 
-- 
2.25.1


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

* [PATCH 4/4] clk: qcom: gcc-msm8916: Add power domain data
  2022-08-05  7:49 [PATCH 0/4] Support dynamic voltage frequency scaling inside clock controller Jun Nie
                   ` (2 preceding siblings ...)
  2022-08-05  7:49 ` [PATCH 3/4] arm64: dts: qcom: add power domain for clk controller Jun Nie
@ 2022-08-05  7:49 ` Jun Nie
  2022-08-05  9:32 ` [PATCH 0/4] Support dynamic voltage frequency scaling inside clock controller Stephan Gerhold
  4 siblings, 0 replies; 10+ messages in thread
From: Jun Nie @ 2022-08-05  7:49 UTC (permalink / raw)
  To: abel.vesa, bjorn.andersson, mturquette, sboyd
  Cc: agross, shawn.guo, bryan.odonoghue, linux-clk, linux-arm-msm,
	devicetree, Jun Nie

Add power domain performance state and ceiling freq mapping table
so that optimal performance point can be voted by clks within
clock controller. This is not related to the clks consumer devices.

Run this command to check genpd perf state:
cat /sys/kernel/debug/pm_genpd/vddcx/perf_state

Signed-off-by: Jun Nie <jun.nie@linaro.org>
---
 drivers/clk/qcom/gcc-msm8916.c | 182 +++++++++++++++++++++++++++++++++
 1 file changed, 182 insertions(+)

diff --git a/drivers/clk/qcom/gcc-msm8916.c b/drivers/clk/qcom/gcc-msm8916.c
index 17e4a5a2a9fd..b42e39688a28 100644
--- a/drivers/clk/qcom/gcc-msm8916.c
+++ b/drivers/clk/qcom/gcc-msm8916.c
@@ -13,8 +13,10 @@
 #include <linux/clk-provider.h>
 #include <linux/regmap.h>
 #include <linux/reset-controller.h>
+#include <linux/mutex.h>
 
 #include <dt-bindings/clock/qcom,gcc-msm8916.h>
+#include <dt-bindings/power/qcom-rpmpd.h>
 #include <dt-bindings/reset/qcom,gcc-msm8916.h>
 
 #include "common.h"
@@ -25,6 +27,20 @@
 #include "reset.h"
 #include "gdsc.h"
 
+static struct device	*genpd_dev;
+static struct mutex	genpd_lock;
+static struct list_head	genpd_head;
+
+#define POWER_PDOPP(table)					\
+	.power_magic = CLK_POWER_MAGIC,				\
+	.power = &(struct clk_power_data) {			\
+		.genpd_head = &genpd_head,			\
+		.genpd_lock = &genpd_lock,			\
+		.genpdopp_table = table,			\
+		.genpdopp_num = ARRAY_SIZE(table),		\
+		.genpd_dev = &genpd_dev,			\
+	}
+
 enum {
 	P_XO,
 	P_GPLL0,
@@ -394,6 +410,11 @@ static const struct freq_tbl ftbl_gcc_camss_ahb_clk[] = {
 	{ }
 };
 
+static const struct genpdopp_table camss_ahb_genpdopp[] = {
+	{RPM_SMD_CORNER_SVS_SOC, 40000000},
+	{RPM_SMD_CORNER_NORMAL, 80000000},
+};
+
 static struct clk_rcg2 camss_ahb_clk_src = {
 	.cmd_rcgr = 0x5a000,
 	.mnd_width = 8,
@@ -405,6 +426,7 @@ static struct clk_rcg2 camss_ahb_clk_src = {
 		.parent_names = gcc_xo_gpll0,
 		.num_parents = 2,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(camss_ahb_genpdopp),
 	},
 };
 
@@ -435,6 +457,11 @@ static const struct freq_tbl ftbl_gcc_camss_csi0_1_clk[] = {
 	{ }
 };
 
+static const struct genpdopp_table camss_csi0_1_genpdopp[] = {
+	{RPM_SMD_CORNER_SVS_SOC, 100000000},
+	{RPM_SMD_CORNER_NORMAL, 200000000},
+};
+
 static struct clk_rcg2 csi0_clk_src = {
 	.cmd_rcgr = 0x4e020,
 	.hid_width = 5,
@@ -445,6 +472,7 @@ static struct clk_rcg2 csi0_clk_src = {
 		.parent_names = gcc_xo_gpll0,
 		.num_parents = 2,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(camss_csi0_1_genpdopp),
 	},
 };
 
@@ -458,6 +486,7 @@ static struct clk_rcg2 csi1_clk_src = {
 		.parent_names = gcc_xo_gpll0,
 		.num_parents = 2,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(camss_csi0_1_genpdopp),
 	},
 };
 
@@ -476,6 +505,12 @@ static const struct freq_tbl ftbl_gcc_oxili_gfx3d_clk[] = {
 	{ }
 };
 
+
+static const struct genpdopp_table gfx3d_genpdopp[] = {
+	{RPM_SMD_CORNER_SVS_SOC, 200000000},
+	{RPM_SMD_CORNER_NORMAL, 310000000},
+	{RPM_SMD_CORNER_SUPER_TURBO, 400000000},
+};
 static struct clk_rcg2 gfx3d_clk_src = {
 	.cmd_rcgr = 0x59000,
 	.hid_width = 5,
@@ -486,6 +521,7 @@ static struct clk_rcg2 gfx3d_clk_src = {
 		.parent_names = gcc_xo_gpll0a_gpll1_gpll2a,
 		.num_parents = 4,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(gfx3d_genpdopp),
 	},
 };
 
@@ -503,6 +539,12 @@ static const struct freq_tbl ftbl_gcc_camss_vfe0_clk[] = {
 	{ }
 };
 
+static const struct genpdopp_table vfe0_genpdopp[] = {
+	{RPM_SMD_CORNER_SVS_SOC, 160000000},
+	{RPM_SMD_CORNER_NORMAL, 320000000},
+	{RPM_SMD_CORNER_SUPER_TURBO, 465000000},
+};
+
 static struct clk_rcg2 vfe0_clk_src = {
 	.cmd_rcgr = 0x58000,
 	.hid_width = 5,
@@ -513,6 +555,7 @@ static struct clk_rcg2 vfe0_clk_src = {
 		.parent_names = gcc_xo_gpll0_gpll2,
 		.num_parents = 3,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(vfe0_genpdopp),
 	},
 };
 
@@ -522,6 +565,10 @@ static const struct freq_tbl ftbl_gcc_blsp1_qup1_6_i2c_apps_clk[] = {
 	{ }
 };
 
+static const struct genpdopp_table qup1_6_i2c_genpdopp[] = {
+	{RPM_SMD_CORNER_SVS_SOC, 50000000},
+};
+
 static struct clk_rcg2 blsp1_qup1_i2c_apps_clk_src = {
 	.cmd_rcgr = 0x0200c,
 	.hid_width = 5,
@@ -532,6 +579,7 @@ static struct clk_rcg2 blsp1_qup1_i2c_apps_clk_src = {
 		.parent_names = gcc_xo_gpll0,
 		.num_parents = 2,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(qup1_6_i2c_genpdopp),
 	},
 };
 
@@ -550,6 +598,11 @@ static const struct freq_tbl ftbl_gcc_blsp1_qup1_6_spi_apps_clk[] = {
 	{ }
 };
 
+static const struct genpdopp_table qup1_6_spi_genpdopp[] = {
+	{RPM_SMD_CORNER_SVS_SOC, 25000000},
+	{RPM_SMD_CORNER_NORMAL, 50000000},
+};
+
 static struct clk_rcg2 blsp1_qup1_spi_apps_clk_src = {
 	.cmd_rcgr = 0x02024,
 	.mnd_width = 8,
@@ -561,6 +614,7 @@ static struct clk_rcg2 blsp1_qup1_spi_apps_clk_src = {
 		.parent_names = gcc_xo_gpll0,
 		.num_parents = 2,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(qup1_6_spi_genpdopp),
 	},
 };
 
@@ -574,6 +628,7 @@ static struct clk_rcg2 blsp1_qup2_i2c_apps_clk_src = {
 		.parent_names = gcc_xo_gpll0,
 		.num_parents = 2,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(qup1_6_i2c_genpdopp),
 	},
 };
 
@@ -588,6 +643,7 @@ static struct clk_rcg2 blsp1_qup2_spi_apps_clk_src = {
 		.parent_names = gcc_xo_gpll0,
 		.num_parents = 2,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(qup1_6_spi_genpdopp),
 	},
 };
 
@@ -601,6 +657,7 @@ static struct clk_rcg2 blsp1_qup3_i2c_apps_clk_src = {
 		.parent_names = gcc_xo_gpll0,
 		.num_parents = 2,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(qup1_6_i2c_genpdopp),
 	},
 };
 
@@ -615,6 +672,7 @@ static struct clk_rcg2 blsp1_qup3_spi_apps_clk_src = {
 		.parent_names = gcc_xo_gpll0,
 		.num_parents = 2,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(qup1_6_spi_genpdopp),
 	},
 };
 
@@ -628,6 +686,7 @@ static struct clk_rcg2 blsp1_qup4_i2c_apps_clk_src = {
 		.parent_names = gcc_xo_gpll0,
 		.num_parents = 2,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(qup1_6_i2c_genpdopp),
 	},
 };
 
@@ -642,6 +701,7 @@ static struct clk_rcg2 blsp1_qup4_spi_apps_clk_src = {
 		.parent_names = gcc_xo_gpll0,
 		.num_parents = 2,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(qup1_6_spi_genpdopp),
 	},
 };
 
@@ -655,6 +715,7 @@ static struct clk_rcg2 blsp1_qup5_i2c_apps_clk_src = {
 		.parent_names = gcc_xo_gpll0,
 		.num_parents = 2,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(qup1_6_i2c_genpdopp),
 	},
 };
 
@@ -669,6 +730,7 @@ static struct clk_rcg2 blsp1_qup5_spi_apps_clk_src = {
 		.parent_names = gcc_xo_gpll0,
 		.num_parents = 2,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(qup1_6_spi_genpdopp),
 	},
 };
 
@@ -682,6 +744,7 @@ static struct clk_rcg2 blsp1_qup6_i2c_apps_clk_src = {
 		.parent_names = gcc_xo_gpll0,
 		.num_parents = 2,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(qup1_6_i2c_genpdopp),
 	},
 };
 
@@ -696,6 +759,7 @@ static struct clk_rcg2 blsp1_qup6_spi_apps_clk_src = {
 		.parent_names = gcc_xo_gpll0,
 		.num_parents = 2,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(qup1_6_spi_genpdopp),
 	},
 };
 
@@ -718,6 +782,11 @@ static const struct freq_tbl ftbl_gcc_blsp1_uart1_6_apps_clk[] = {
 	{ }
 };
 
+static const struct genpdopp_table uart1_2_genpdopp[] = {
+	{RPM_SMD_CORNER_SVS_SOC, 32000000},
+	{RPM_SMD_CORNER_NORMAL, 64000000},
+};
+
 static struct clk_rcg2 blsp1_uart1_apps_clk_src = {
 	.cmd_rcgr = 0x02044,
 	.mnd_width = 16,
@@ -729,6 +798,7 @@ static struct clk_rcg2 blsp1_uart1_apps_clk_src = {
 		.parent_names = gcc_xo_gpll0,
 		.num_parents = 2,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(uart1_2_genpdopp),
 	},
 };
 
@@ -743,6 +813,7 @@ static struct clk_rcg2 blsp1_uart2_apps_clk_src = {
 		.parent_names = gcc_xo_gpll0,
 		.num_parents = 2,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(uart1_2_genpdopp),
 	},
 };
 
@@ -751,6 +822,10 @@ static const struct freq_tbl ftbl_gcc_camss_cci_clk[] = {
 	{ }
 };
 
+static const struct genpdopp_table cci_genpdopp[] = {
+	{RPM_SMD_CORNER_SVS_SOC, 19200000},
+};
+
 static struct clk_rcg2 cci_clk_src = {
 	.cmd_rcgr = 0x51000,
 	.mnd_width = 8,
@@ -762,6 +837,7 @@ static struct clk_rcg2 cci_clk_src = {
 		.parent_names = gcc_xo_gpll0a,
 		.num_parents = 2,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(cci_genpdopp),
 	},
 };
 
@@ -771,6 +847,11 @@ static const struct freq_tbl ftbl_gcc_camss_gp0_1_clk[] = {
 	{ }
 };
 
+static const struct genpdopp_table gp0_1_genpdopp[] = {
+	{RPM_SMD_CORNER_SVS_SOC, 100000000},
+	{RPM_SMD_CORNER_NORMAL, 200000000},
+};
+
 static struct clk_rcg2 camss_gp0_clk_src = {
 	.cmd_rcgr = 0x54000,
 	.mnd_width = 8,
@@ -782,6 +863,7 @@ static struct clk_rcg2 camss_gp0_clk_src = {
 		.parent_names = gcc_xo_gpll0_gpll1a_sleep,
 		.num_parents = 4,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(gp0_1_genpdopp),
 	},
 };
 
@@ -796,6 +878,7 @@ static struct clk_rcg2 camss_gp1_clk_src = {
 		.parent_names = gcc_xo_gpll0_gpll1a_sleep,
 		.num_parents = 4,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(gp0_1_genpdopp),
 	},
 };
 
@@ -806,6 +889,12 @@ static const struct freq_tbl ftbl_gcc_camss_jpeg0_clk[] = {
 	{ }
 };
 
+static const struct genpdopp_table jpeg0_genpdopp[] = {
+	{RPM_SMD_CORNER_SVS_SOC, 133330000},
+	{RPM_SMD_CORNER_NORMAL, 266670000},
+	{RPM_SMD_CORNER_SUPER_TURBO, 320000000},
+};
+
 static struct clk_rcg2 jpeg0_clk_src = {
 	.cmd_rcgr = 0x57000,
 	.hid_width = 5,
@@ -816,6 +905,7 @@ static struct clk_rcg2 jpeg0_clk_src = {
 		.parent_names = gcc_xo_gpll0,
 		.num_parents = 2,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(jpeg0_genpdopp),
 	},
 };
 
@@ -826,6 +916,11 @@ static const struct freq_tbl ftbl_gcc_camss_mclk0_1_clk[] = {
 	{ }
 };
 
+static const struct genpdopp_table mclk0_1_genpdopp[] = {
+	{RPM_SMD_CORNER_SVS_SOC, 24000000},
+	{RPM_SMD_CORNER_NORMAL, 66670000},
+};
+
 static struct clk_rcg2 mclk0_clk_src = {
 	.cmd_rcgr = 0x52000,
 	.mnd_width = 8,
@@ -837,6 +932,7 @@ static struct clk_rcg2 mclk0_clk_src = {
 		.parent_names = gcc_xo_gpll0_gpll1a_sleep,
 		.num_parents = 4,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(mclk0_1_genpdopp),
 	},
 };
 
@@ -851,6 +947,7 @@ static struct clk_rcg2 mclk1_clk_src = {
 		.parent_names = gcc_xo_gpll0_gpll1a_sleep,
 		.num_parents = 4,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(mclk0_1_genpdopp),
 	},
 };
 
@@ -873,6 +970,11 @@ static struct clk_rcg2 csi0phytimer_clk_src = {
 	},
 };
 
+static const struct genpdopp_table csi1phytimer_genpdopp[] = {
+	{RPM_SMD_CORNER_SVS_SOC, 100000000},
+	{RPM_SMD_CORNER_NORMAL, 200000000},
+};
+
 static struct clk_rcg2 csi1phytimer_clk_src = {
 	.cmd_rcgr = 0x4f000,
 	.hid_width = 5,
@@ -883,6 +985,7 @@ static struct clk_rcg2 csi1phytimer_clk_src = {
 		.parent_names = gcc_xo_gpll0_gpll1a,
 		.num_parents = 3,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(csi1phytimer_genpdopp),
 	},
 };
 
@@ -893,6 +996,12 @@ static const struct freq_tbl ftbl_gcc_camss_cpp_clk[] = {
 	{ }
 };
 
+static const struct genpdopp_table cpp_genpdopp[] = {
+	{RPM_SMD_CORNER_SVS_SOC, 160000000},
+	{RPM_SMD_CORNER_NORMAL, 320000000},
+	{RPM_SMD_CORNER_SUPER_TURBO, 465000000},
+};
+
 static struct clk_rcg2 cpp_clk_src = {
 	.cmd_rcgr = 0x58018,
 	.hid_width = 5,
@@ -903,6 +1012,7 @@ static struct clk_rcg2 cpp_clk_src = {
 		.parent_names = gcc_xo_gpll0_gpll2,
 		.num_parents = 3,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(cpp_genpdopp),
 	},
 };
 
@@ -914,6 +1024,11 @@ static const struct freq_tbl ftbl_gcc_crypto_clk[] = {
 	{ }
 };
 
+static const struct genpdopp_table crypto_genpdopp[] = {
+		{RPM_SMD_CORNER_SVS_SOC, 80000000},
+		{RPM_SMD_CORNER_NORMAL, 160000000},
+};
+
 static struct clk_rcg2 crypto_clk_src = {
 	.cmd_rcgr = 0x16004,
 	.hid_width = 5,
@@ -924,6 +1039,7 @@ static struct clk_rcg2 crypto_clk_src = {
 		.parent_names = gcc_xo_gpll0,
 		.num_parents = 2,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(crypto_genpdopp),
 	},
 };
 
@@ -932,6 +1048,11 @@ static const struct freq_tbl ftbl_gcc_gp1_3_clk[] = {
 	{ }
 };
 
+static const struct genpdopp_table gp1_3_genpdopp[] = {
+	{RPM_SMD_CORNER_SVS_SOC, 100000000},
+	{RPM_SMD_CORNER_NORMAL, 200000000},
+};
+
 static struct clk_rcg2 gp1_clk_src = {
 	.cmd_rcgr = 0x08004,
 	.mnd_width = 8,
@@ -943,6 +1064,7 @@ static struct clk_rcg2 gp1_clk_src = {
 		.parent_names = gcc_xo_gpll0_gpll1a_sleep,
 		.num_parents = 3,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(gp1_3_genpdopp),
 	},
 };
 
@@ -957,6 +1079,7 @@ static struct clk_rcg2 gp2_clk_src = {
 		.parent_names = gcc_xo_gpll0_gpll1a_sleep,
 		.num_parents = 3,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(gp1_3_genpdopp),
 	},
 };
 
@@ -971,9 +1094,15 @@ static struct clk_rcg2 gp3_clk_src = {
 		.parent_names = gcc_xo_gpll0_gpll1a_sleep,
 		.num_parents = 3,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(gp1_3_genpdopp),
 	},
 };
 
+static const struct genpdopp_table byte0_genpdopp[] = {
+	{RPM_SMD_CORNER_SVS_SOC, 94400000},
+	{RPM_SMD_CORNER_NORMAL, 188500000},
+};
+
 static struct clk_rcg2 byte0_clk_src = {
 	.cmd_rcgr = 0x4d044,
 	.hid_width = 5,
@@ -984,6 +1113,7 @@ static struct clk_rcg2 byte0_clk_src = {
 		.num_parents = 3,
 		.ops = &clk_byte2_ops,
 		.flags = CLK_SET_RATE_PARENT,
+		POWER_PDOPP(byte0_genpdopp),
 	},
 };
 
@@ -992,6 +1122,10 @@ static const struct freq_tbl ftbl_gcc_mdss_esc0_clk[] = {
 	{ }
 };
 
+static const struct genpdopp_table esc0_genpdopp[] = {
+	{RPM_SMD_CORNER_SVS_SOC, 19200000},
+};
+
 static struct clk_rcg2 esc0_clk_src = {
 	.cmd_rcgr = 0x4d05c,
 	.hid_width = 5,
@@ -1002,6 +1136,7 @@ static struct clk_rcg2 esc0_clk_src = {
 		.parent_names = gcc_xo_dsibyte,
 		.num_parents = 2,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(esc0_genpdopp),
 	},
 };
 
@@ -1017,6 +1152,12 @@ static const struct freq_tbl ftbl_gcc_mdss_mdp_clk[] = {
 	{ }
 };
 
+static const struct genpdopp_table mdp_genpdopp[] = {
+	{RPM_SMD_CORNER_SVS_SOC, 160000000},
+	{RPM_SMD_CORNER_NORMAL, 266670000},
+	{RPM_SMD_CORNER_SUPER_TURBO, 320000000},
+};
+
 static struct clk_rcg2 mdp_clk_src = {
 	.cmd_rcgr = 0x4d014,
 	.hid_width = 5,
@@ -1027,9 +1168,15 @@ static struct clk_rcg2 mdp_clk_src = {
 		.parent_names = gcc_xo_gpll0_dsiphy,
 		.num_parents = 3,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(mdp_genpdopp),
 	},
 };
 
+static const struct genpdopp_table pclk0_genpdopp[] = {
+	{RPM_SMD_CORNER_SVS_SOC, 150000000},
+	{RPM_SMD_CORNER_NORMAL, 250000000},
+};
+
 static struct clk_rcg2 pclk0_clk_src = {
 	.cmd_rcgr = 0x4d000,
 	.mnd_width = 8,
@@ -1041,6 +1188,7 @@ static struct clk_rcg2 pclk0_clk_src = {
 		.num_parents = 3,
 		.ops = &clk_pixel_ops,
 		.flags = CLK_SET_RATE_PARENT,
+		POWER_PDOPP(pclk0_genpdopp),
 	},
 };
 
@@ -1049,6 +1197,10 @@ static const struct freq_tbl ftbl_gcc_mdss_vsync_clk[] = {
 	{ }
 };
 
+static const struct genpdopp_table vsync_genpdopp[] = {
+	{RPM_SMD_CORNER_SVS_SOC, 19200000},
+};
+
 static struct clk_rcg2 vsync_clk_src = {
 	.cmd_rcgr = 0x4d02c,
 	.hid_width = 5,
@@ -1059,6 +1211,7 @@ static struct clk_rcg2 vsync_clk_src = {
 		.parent_names = gcc_xo_gpll0a,
 		.num_parents = 2,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(vsync_genpdopp),
 	},
 };
 
@@ -1067,6 +1220,10 @@ static const struct freq_tbl ftbl_gcc_pdm2_clk[] = {
 	{ }
 };
 
+static const struct genpdopp_table pdm2_genpdopp[] = {
+	{RPM_SMD_CORNER_SVS_SOC, 64000000},
+};
+
 static struct clk_rcg2 pdm2_clk_src = {
 	.cmd_rcgr = 0x44010,
 	.hid_width = 5,
@@ -1077,6 +1234,7 @@ static struct clk_rcg2 pdm2_clk_src = {
 		.parent_names = gcc_xo_gpll0,
 		.num_parents = 2,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(pdm2_genpdopp),
 	},
 };
 
@@ -1091,6 +1249,11 @@ static const struct freq_tbl ftbl_gcc_sdcc1_apps_clk[] = {
 	{ }
 };
 
+static const struct genpdopp_table sdcc1_2_genpdopp[] = {
+	{RPM_SMD_CORNER_SVS_SOC, 50000000},
+	{RPM_SMD_CORNER_NORMAL, 200000000},
+};
+
 static struct clk_rcg2 sdcc1_apps_clk_src = {
 	.cmd_rcgr = 0x42004,
 	.mnd_width = 8,
@@ -1102,6 +1265,7 @@ static struct clk_rcg2 sdcc1_apps_clk_src = {
 		.parent_names = gcc_xo_gpll0,
 		.num_parents = 2,
 		.ops = &clk_rcg2_floor_ops,
+		POWER_PDOPP(sdcc1_2_genpdopp),
 	},
 };
 
@@ -1127,6 +1291,7 @@ static struct clk_rcg2 sdcc2_apps_clk_src = {
 		.parent_names = gcc_xo_gpll0,
 		.num_parents = 2,
 		.ops = &clk_rcg2_floor_ops,
+		POWER_PDOPP(sdcc1_2_genpdopp),
 	},
 };
 
@@ -1179,6 +1344,11 @@ static const struct freq_tbl ftbl_gcc_usb_hs_system_clk[] = {
 	{ }
 };
 
+static const struct genpdopp_table usb_hs_system_genpdopp[] = {
+	{RPM_SMD_CORNER_SVS_SOC, 57140000},
+	{RPM_SMD_CORNER_NORMAL, 80000000},
+};
+
 static struct clk_rcg2 usb_hs_system_clk_src = {
 	.cmd_rcgr = 0x41010,
 	.hid_width = 5,
@@ -1189,6 +1359,7 @@ static struct clk_rcg2 usb_hs_system_clk_src = {
 		.parent_names = gcc_xo_gpll0,
 		.num_parents = 2,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(usb_hs_system_genpdopp),
 	},
 };
 
@@ -1506,6 +1677,12 @@ static const struct freq_tbl ftbl_gcc_venus0_vcodec0_clk[] = {
 	{ }
 };
 
+static const struct genpdopp_table vcodec0_genpdopp[] = {
+		{RPM_SMD_CORNER_SVS_SOC, 100000000},
+		{RPM_SMD_CORNER_NORMAL, 160000000},
+		{RPM_SMD_CORNER_SUPER_TURBO, 228570000},
+};
+
 static struct clk_rcg2 vcodec0_clk_src = {
 	.cmd_rcgr = 0x4C000,
 	.mnd_width = 8,
@@ -1517,6 +1694,7 @@ static struct clk_rcg2 vcodec0_clk_src = {
 		.parent_names = gcc_xo_gpll0,
 		.num_parents = 2,
 		.ops = &clk_rcg2_ops,
+		POWER_PDOPP(vcodec0_genpdopp),
 	},
 };
 
@@ -3389,6 +3567,10 @@ static int gcc_msm8916_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
+	genpd_dev = dev;
+	mutex_init(&genpd_lock);
+	INIT_LIST_HEAD(&genpd_head);
+
 	return qcom_cc_probe(pdev, &gcc_msm8916_desc);
 }
 
-- 
2.25.1


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

* Re: [PATCH 0/4] Support dynamic voltage frequency scaling inside clock controller
  2022-08-05  7:49 [PATCH 0/4] Support dynamic voltage frequency scaling inside clock controller Jun Nie
                   ` (3 preceding siblings ...)
  2022-08-05  7:49 ` [PATCH 4/4] clk: qcom: gcc-msm8916: Add power domain data Jun Nie
@ 2022-08-05  9:32 ` Stephan Gerhold
  2022-08-06  4:43   ` Jun Nie
  4 siblings, 1 reply; 10+ messages in thread
From: Stephan Gerhold @ 2022-08-05  9:32 UTC (permalink / raw)
  To: Jun Nie
  Cc: abel.vesa, bjorn.andersson, mturquette, sboyd, agross, shawn.guo,
	bryan.odonoghue, linux-clk, linux-arm-msm, devicetree

On Fri, Aug 05, 2022 at 03:49:31PM +0800, Jun Nie wrote:
> Support dynamic voltage frequency scaling inside clock controller with
> changes in clock framework. And added msm8916 as the first SoC to
> support this feature.
> 

As far as I understand it was decided to handle this on the consumer
driver side in mainline, together with OPP tables and "required-opps" in
the device tree. If you look at e.g. sc7180.dtsi you can see that this
is heavily used there. Also see e.g. [1] for some links to related
discussions.

For MSM8916 at least the SDHCI and DSI driver should support this 
already. Some other older drivers (e.g. QUP, USB) would need some change
similar to [2] (just like they still need changes for interconnects).

I'm not entirely sure why it was decided to not do this as part of the
clock core (maybe someone can explain or link a relevant mailing list
post?), but we should try to keep it consistent in any case. :)

Thanks,
Stephan

[1]: https://lore.kernel.org/linux-arm-msm/20200910162610.GA7008@gerhold.net/
[2]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0472f8d3c054a0ff58122fc9d2dbf84f197a284f

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

* Re: [PATCH 0/4] Support dynamic voltage frequency scaling inside clock controller
  2022-08-05  9:32 ` [PATCH 0/4] Support dynamic voltage frequency scaling inside clock controller Stephan Gerhold
@ 2022-08-06  4:43   ` Jun Nie
  0 siblings, 0 replies; 10+ messages in thread
From: Jun Nie @ 2022-08-06  4:43 UTC (permalink / raw)
  To: Stephan Gerhold
  Cc: abel.vesa, bjorn.andersson, mturquette, sboyd, agross, shawn.guo,
	bryan.odonoghue, linux-clk, linux-arm-msm, devicetree

Stephan Gerhold <stephan@gerhold.net> 于2022年8月5日周五 17:32写道:
>
> On Fri, Aug 05, 2022 at 03:49:31PM +0800, Jun Nie wrote:
> > Support dynamic voltage frequency scaling inside clock controller with
> > changes in clock framework. And added msm8916 as the first SoC to
> > support this feature.
> >
>
> As far as I understand it was decided to handle this on the consumer
> driver side in mainline, together with OPP tables and "required-opps" in
> the device tree. If you look at e.g. sc7180.dtsi you can see that this
> is heavily used there. Also see e.g. [1] for some links to related
> discussions.
>
> For MSM8916 at least the SDHCI and DSI driver should support this
> already. Some other older drivers (e.g. QUP, USB) would need some change
> similar to [2] (just like they still need changes for interconnects).
>
> I'm not entirely sure why it was decided to not do this as part of the
> clock core (maybe someone can explain or link a relevant mailing list
> post?), but we should try to keep it consistent in any case. :)
>
> Thanks,
> Stephan

Hi Stephan,
Thanks for the reminder! My work in clk framework was done 2 years ago actually.
I guess it is just before the decision to use consumer side opps for
this, because
I did not see any solution at the time.

I think the consumer side required-opps is better than my solution.
Because clock
is infrastructure to initialize other devices in most cases. If clock
device depends
on power domains, we have to initialize the power domain first. So adjustment in
initialization sequence of many devices is needed sometimes. The consumer side
operation avoid such inconvenience.

So let's forget this patch set.

Regards,
Jun

>
> [1]: https://lore.kernel.org/linux-arm-msm/20200910162610.GA7008@gerhold.net/
> [2]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0472f8d3c054a0ff58122fc9d2dbf84f197a284f

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

* Re: [PATCH 2/4] soc: qcom: rpmpd: Add corner power-domains states
  2022-08-05  7:49 ` [PATCH 2/4] soc: qcom: rpmpd: Add corner power-domains states Jun Nie
@ 2022-09-26 16:29   ` Bjorn Andersson
  2022-10-24  4:27     ` Jun Nie
  0 siblings, 1 reply; 10+ messages in thread
From: Bjorn Andersson @ 2022-09-26 16:29 UTC (permalink / raw)
  To: Jun Nie
  Cc: abel.vesa, bjorn.andersson, mturquette, sboyd, agross, shawn.guo,
	bryan.odonoghue, linux-clk, linux-arm-msm, devicetree

On Fri, Aug 05, 2022 at 03:49:33PM +0800, Jun Nie wrote:
> Some SoCs use corner instead of level in rpm regulator, such as
> MSM8916 and MSM8939. Add these power-domains states value so that
> devices can vote them.
> 
> Note that there is a shift with 1 when converting the value from
> regulator usage in Qualcomm Linux 3.18 to power domain usage here.
> Because corner is not well hacked in regulator framework in 3.18.
> For example, RPM_REGULATOR_CORNER_RETENTION is 2 in 3.18 while
> RPM_SMD_CORNER_RETENTION is 1.
> 

How about we just stick with the numbers in the rpmpd node in DT, as
that would be the only place these constants are used and all the actual
users can use the label associated there?

Regards,
Bjorn

> Signed-off-by: Jun Nie <jun.nie@linaro.org>
> ---
>  include/dt-bindings/power/qcom-rpmpd.h | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/include/dt-bindings/power/qcom-rpmpd.h b/include/dt-bindings/power/qcom-rpmpd.h
> index 6cce5b7aa940..f778dbbf083d 100644
> --- a/include/dt-bindings/power/qcom-rpmpd.h
> +++ b/include/dt-bindings/power/qcom-rpmpd.h
> @@ -297,4 +297,12 @@
>  #define RPM_SMD_LEVEL_TURBO_HIGH      448
>  #define RPM_SMD_LEVEL_BINNING         512
>  
> +/* RPM SMD Power Domain performance levels in regulator corner method */
> +#define RPM_SMD_CORNER_RETENTION	1
> +#define RPM_SMD_CORNER_SVS_KRAIT	2
> +#define RPM_SMD_CORNER_SVS_SOC		3
> +#define RPM_SMD_CORNER_NORMAL		4
> +#define RPM_SMD_CORNER_TURBO		5
> +#define RPM_SMD_CORNER_SUPER_TURBO	6
> +
>  #endif
> -- 
> 2.25.1
> 

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

* Re: [PATCH 3/4] arm64: dts: qcom: add power domain for clk controller
  2022-08-05  7:49 ` [PATCH 3/4] arm64: dts: qcom: add power domain for clk controller Jun Nie
@ 2022-09-26 16:33   ` Bjorn Andersson
  0 siblings, 0 replies; 10+ messages in thread
From: Bjorn Andersson @ 2022-09-26 16:33 UTC (permalink / raw)
  To: Jun Nie
  Cc: abel.vesa, bjorn.andersson, mturquette, sboyd, agross, shawn.guo,
	bryan.odonoghue, linux-clk, linux-arm-msm, devicetree

On Fri, Aug 05, 2022 at 03:49:34PM +0800, Jun Nie wrote:
> Add RPM power domain for clk controller so that clock controller can
> use it for dynamic voltage frequency scaling.
> 
> Also replace the RPM power domain value with defninition.
> 
> Signed-off-by: Jun Nie <jun.nie@linaro.org>
> ---
>  arch/arm64/boot/dts/qcom/msm8916.dtsi | 14 ++++++++------
>  1 file changed, 8 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> index 05472510e29d..fdb32b3a23e8 100644
> --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
> +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> @@ -312,22 +312,22 @@ rpmpd_opp_table: opp-table {
>  						compatible = "operating-points-v2";
>  
>  						rpmpd_opp_ret: opp1 {
> -							opp-level = <1>;
> +							opp-level = <RPM_SMD_CORNER_RETENTION>;
>  						};
>  						rpmpd_opp_svs_krait: opp2 {
> -							opp-level = <2>;
> +							opp-level = <RPM_SMD_CORNER_SVS_KRAIT>;
>  						};
>  						rpmpd_opp_svs_soc: opp3 {
> -							opp-level = <3>;
> +							opp-level = <RPM_SMD_CORNER_SVS_SOC>;
>  						};
>  						rpmpd_opp_nom: opp4 {
> -							opp-level = <4>;
> +							opp-level = <RPM_SMD_CORNER_NORMAL>;
>  						};
>  						rpmpd_opp_turbo: opp5 {
> -							opp-level = <5>;
> +							opp-level = <RPM_SMD_CORNER_TURBO>;
>  						};
>  						rpmpd_opp_super_turbo: opp6 {
> -							opp-level = <6>;
> +							opp-level = <RPM_SMD_CORNER_SUPER_TURBO>;

See comment on previous patch, I think it's fine to stick with the
numerical values here, as the label gives them meaning to the clients.

>  						};
>  					};
>  				};
> @@ -933,6 +933,8 @@ gcc: clock-controller@1800000 {
>  			#clock-cells = <1>;
>  			#reset-cells = <1>;
>  			#power-domain-cells = <1>;
> +			power-domains = <&rpmpd MSM8916_VDDCX>;
> +			power-domain-names = "vdd";

This makes sense even without your patches, as it creates a relationship
between gdscs of the clock-controller and VDDCX - such that enable and
performance state of the gdscs propagates up to VDDCX.

Could you please check that this seems to work properly?


PS. We don't need power-domain-names.

Regards,
Bjorn

>  			reg = <0x01800000 0x80000>;
>  		};
>  
> -- 
> 2.25.1
> 

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

* Re: [PATCH 2/4] soc: qcom: rpmpd: Add corner power-domains states
  2022-09-26 16:29   ` Bjorn Andersson
@ 2022-10-24  4:27     ` Jun Nie
  0 siblings, 0 replies; 10+ messages in thread
From: Jun Nie @ 2022-10-24  4:27 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: abel.vesa, bjorn.andersson, mturquette, sboyd, agross, shawn.guo,
	bryan.odonoghue, linux-clk, linux-arm-msm, devicetree

Bjorn Andersson <andersson@kernel.org> 于2022年9月27日周二 00:29写道:
>
> On Fri, Aug 05, 2022 at 03:49:33PM +0800, Jun Nie wrote:
> > Some SoCs use corner instead of level in rpm regulator, such as
> > MSM8916 and MSM8939. Add these power-domains states value so that
> > devices can vote them.
> >
> > Note that there is a shift with 1 when converting the value from
> > regulator usage in Qualcomm Linux 3.18 to power domain usage here.
> > Because corner is not well hacked in regulator framework in 3.18.
> > For example, RPM_REGULATOR_CORNER_RETENTION is 2 in 3.18 while
> > RPM_SMD_CORNER_RETENTION is 1.
> >
>
> How about we just stick with the numbers in the rpmpd node in DT, as
> that would be the only place these constants are used and all the actual
> users can use the label associated there?
>
> Regards,
> Bjorn

The clock driver change in this patch set, the consumer of the
regulator, is dropped. So there
is no more consumers that need the name. So this whole patch set can
be abandoned now.

Regards,
Jun
>
> > Signed-off-by: Jun Nie <jun.nie@linaro.org>
> > ---
> >  include/dt-bindings/power/qcom-rpmpd.h | 8 ++++++++
> >  1 file changed, 8 insertions(+)
> >
> > diff --git a/include/dt-bindings/power/qcom-rpmpd.h b/include/dt-bindings/power/qcom-rpmpd.h
> > index 6cce5b7aa940..f778dbbf083d 100644
> > --- a/include/dt-bindings/power/qcom-rpmpd.h
> > +++ b/include/dt-bindings/power/qcom-rpmpd.h
> > @@ -297,4 +297,12 @@
> >  #define RPM_SMD_LEVEL_TURBO_HIGH      448
> >  #define RPM_SMD_LEVEL_BINNING         512
> >
> > +/* RPM SMD Power Domain performance levels in regulator corner method */
> > +#define RPM_SMD_CORNER_RETENTION     1
> > +#define RPM_SMD_CORNER_SVS_KRAIT     2
> > +#define RPM_SMD_CORNER_SVS_SOC               3
> > +#define RPM_SMD_CORNER_NORMAL                4
> > +#define RPM_SMD_CORNER_TURBO         5
> > +#define RPM_SMD_CORNER_SUPER_TURBO   6
> > +
> >  #endif
> > --
> > 2.25.1
> >

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

end of thread, other threads:[~2022-10-24  4:27 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-05  7:49 [PATCH 0/4] Support dynamic voltage frequency scaling inside clock controller Jun Nie
2022-08-05  7:49 ` [PATCH 1/4] clk: Aggregate power operation in " Jun Nie
2022-08-05  7:49 ` [PATCH 2/4] soc: qcom: rpmpd: Add corner power-domains states Jun Nie
2022-09-26 16:29   ` Bjorn Andersson
2022-10-24  4:27     ` Jun Nie
2022-08-05  7:49 ` [PATCH 3/4] arm64: dts: qcom: add power domain for clk controller Jun Nie
2022-09-26 16:33   ` Bjorn Andersson
2022-08-05  7:49 ` [PATCH 4/4] clk: qcom: gcc-msm8916: Add power domain data Jun Nie
2022-08-05  9:32 ` [PATCH 0/4] Support dynamic voltage frequency scaling inside clock controller Stephan Gerhold
2022-08-06  4:43   ` Jun Nie

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.