From 8c348bebe1f0b9e0f0608321713f32c61da45206 Mon Sep 17 00:00:00 2001
From: Taniya Das <tdas@codeaurora.org>
Date: Sat, 3 Dec 2016 19:06:59 +0530
Subject: [PATCH] clk: Add vdd_class support for handoff and use_max_uV

Some dedicated power rails do not require a max voltage vote during bootup.
Allow clock drivers to skip handoff for the corresponding VDD classes.

Multiple vdd_class structures might share same set of regulators. If the
FMAXes for these different vdd_class structures do not have the same level
vote, there could be a conflict when setting voltage on the regulator.
Add a flag use_max_uV to vote for INT_MAX as max_uV when calling
regulator_set_voltage(). Constraints in the regulator driver make sure that
the final voltage meets the requirement of that regulator's operational
range.

Change-Id: I15c9dc3ecf907723a136cbe90597ccafeba91af0
Signed-off-by: Taniya Das <tdas@codeaurora.org>
---
 drivers/clk/clk.c            | 11 ++++++++---
 include/linux/clk-provider.h |  4 ++++
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index c1865f9ee8b3..eb44cf9ddd17 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -656,7 +656,7 @@ static int clk_update_vdd(struct clk_vdd_class *vdd_class)
 		pr_debug("Set Voltage level Min %d, Max %d\n", uv[new_base + i],
 				uv[max_lvl + i]);
 		rc = regulator_set_voltage(r[i], uv[new_base + i],
-				uv[max_lvl + i]);
+			vdd_class->use_max_uV ? INT_MAX : uv[max_lvl + i]);
 		if (rc)
 			goto set_voltage_fail;
 
@@ -677,11 +677,13 @@ static int clk_update_vdd(struct clk_vdd_class *vdd_class)
 	return rc;
 
 enable_disable_fail:
-	regulator_set_voltage(r[i], uv[cur_base + i], uv[max_lvl + i]);
+	regulator_set_voltage(r[i], uv[cur_base + i],
+			vdd_class->use_max_uV ? INT_MAX : uv[max_lvl + i]);
 
 set_voltage_fail:
 	for (i--; i >= 0; i--) {
-		regulator_set_voltage(r[i], uv[cur_base + i], uv[max_lvl + i]);
+		regulator_set_voltage(r[i], uv[cur_base + i],
+		       vdd_class->use_max_uV ? INT_MAX : uv[max_lvl + i]);
 		if (cur_lvl == 0 || cur_lvl == vdd_class->num_levels)
 			regulator_disable(r[i]);
 		else if (level == 0)
@@ -792,6 +794,9 @@ static int clk_vdd_class_init(struct clk_vdd_class *vdd)
 {
 	struct clk_handoff_vdd *v;
 
+	if (vdd->skip_handoff)
+		return 0;
+
 	list_for_each_entry(v, &clk_handoff_vdd_list, list) {
 		if (v->vdd_class == vdd)
 			return 0;
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index aed90a4902c7..5cd588fa9f6a 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -269,6 +269,8 @@ struct regulator;
 		regulator
  * @level_votes: array of votes for each level
  * @num_levels: specifies the size of level_votes array
+ * @skip_handoff: do not vote for the max possible voltage during init
+ * @use_max_uV: use INT_MAX for max_uV when calling regulator_set_voltage
  * @cur_level: the currently set voltage level
  * @lock: lock to protect this struct
  */
@@ -280,6 +282,8 @@ struct clk_vdd_class {
 	int *vdd_uv;
 	int *level_votes;
 	int num_levels;
+	bool skip_handoff;
+	bool use_max_uV;
 	unsigned long cur_level;
 	struct mutex lock;
 };