msm: krait-regulator: set LDO 50mV below the requested voltage

The requests to the krait ldos are not for the voltage
on the krait. Instead these requests are for the minimum
voltage on the pmic gang to support that krait's chosen frequency.

Update the LDO threshold such that we switch to LDO only for pmic
gang requests below 0.85 volts. This voltage request on the pmic is
low enough to warrant a switch to LDO.

Note that 0.85 volts at the pmic could be requested for multiple
dcvs points. We don't know how much voltage is expected at the krait
in such a case. Set the LDO output to 50mV lesser than the requested
pmic gang voltage.

Change-Id: Ia93e336901a208a4f017fff30e9c5ac7d8b13102
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
diff --git a/Documentation/devicetree/bindings/regulator/krait-regulator.txt b/Documentation/devicetree/bindings/regulator/krait-regulator.txt
index e3da903..149445d 100644
--- a/Documentation/devicetree/bindings/regulator/krait-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/krait-regulator.txt
@@ -10,10 +10,17 @@
 				"mdd" - string to identify the area where mdd registers reside.
 - qcom,headroom-voltage:	The minimum required voltage drop between the input
 			 	voltage and the output voltage for the LDO to be
-			 	operational, in microvolts
-- qcom,retention-voltage:	The value for retention voltage in microvolts
-- qcom,ldo-default-voltage:	The default value for LDO voltage in microvolts
-- qcom,ldo-threshold-voltage:	The voltage value above which LDO is nonfunctional
+			 	operational, in microvolts. Acceptable values are from
+				50000uV to 250000uV
+- qcom,retention-voltage:	The value for retention voltage in microvolts. Acceptable
+				values are from 465000uV to 750000uV
+- qcom,ldo-default-voltage:	The default value for LDO voltage in microvolts. Acceptable
+				values are from 465000uV to 750000uV
+- qcom,ldo-threshold-voltage:	The voltage value above which LDO is nonfunctional.
+				Acceptable values are from 600000uV to 900000uV
+- qcom,ldo-delta-voltage:	The delta used to reduce the requested voltage in order
+				to derive the LDO output voltage while switching
+				to LDO mode. Acceptable values are from 1000uV to 100000uV
 
 Any property defined as part of the core regulator
 binding, defined in regulator.txt, can also be used.
@@ -31,5 +38,6 @@
 		qcom,retention-voltage = <745000>;
 		qcom,ldo-default-voltage = <745000>;
 		qcom,ldo-threshold-voltage = <750000>;
+		qcom,ldo-delta-voltage = <50000>;
 	};
 
diff --git a/arch/arm/boot/dts/msm8974-regulator.dtsi b/arch/arm/boot/dts/msm8974-regulator.dtsi
index 368db78..bac7a73 100644
--- a/arch/arm/boot/dts/msm8974-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974-regulator.dtsi
@@ -426,7 +426,8 @@
 		qcom,headroom-voltage = <150000>;
 		qcom,retention-voltage = <675000>;
 		qcom,ldo-default-voltage = <750000>;
-		qcom,ldo-threshold-voltage = <750000>;
+		qcom,ldo-threshold-voltage = <850000>;
+		qcom,ldo-delta-voltage = <50000>;
 	};
 
 	krait1_vreg: regulator@f9098000 {
@@ -440,7 +441,8 @@
 		qcom,headroom-voltage = <150000>;
 		qcom,retention-voltage = <675000>;
 		qcom,ldo-default-voltage = <750000>;
-		qcom,ldo-threshold-voltage = <750000>;
+		qcom,ldo-threshold-voltage = <850000>;
+		qcom,ldo-delta-voltage = <50000>;
 	};
 
 	krait2_vreg: regulator@f90a8000 {
@@ -454,7 +456,8 @@
 		qcom,headroom-voltage = <150000>;
 		qcom,retention-voltage = <675000>;
 		qcom,ldo-default-voltage = <750000>;
-		qcom,ldo-threshold-voltage = <750000>;
+		qcom,ldo-threshold-voltage = <850000>;
+		qcom,ldo-delta-voltage = <50000>;
 	};
 
 	krait3_vreg: regulator@f90b8000 {
@@ -468,7 +471,8 @@
 		qcom,headroom-voltage = <150000>;
 		qcom,retention-voltage = <675000>;
 		qcom,ldo-default-voltage = <750000>;
-		qcom,ldo-threshold-voltage = <750000>;
+		qcom,ldo-threshold-voltage = <850000>;
+		qcom,ldo-delta-voltage = <50000>;
 	};
 
 	spi_eth_vreg: spi_eth_phy_vreg {
diff --git a/arch/arm/mach-msm/krait-regulator.c b/arch/arm/mach-msm/krait-regulator.c
index b6d6965..a54fddf 100644
--- a/arch/arm/mach-msm/krait-regulator.c
+++ b/arch/arm/mach-msm/krait-regulator.c
@@ -162,6 +162,7 @@
 	int				retention_uV;
 	int				headroom_uV;
 	int				ldo_threshold_uV;
+	int				ldo_delta_uV;
 	bool				online;
 };
 
@@ -260,7 +261,8 @@
 
 static int switch_to_using_ldo(struct krait_power_vreg *kvreg)
 {
-	if (kvreg->mode == LDO_MODE && get_krait_ldo_uv(kvreg) == kvreg->uV)
+	if (kvreg->mode == LDO_MODE
+		&& get_krait_ldo_uv(kvreg) == kvreg->uV - kvreg->ldo_delta_uV)
 		return 0;
 
 	/*
@@ -270,7 +272,7 @@
 	if (kvreg->mode == LDO_MODE)
 		switch_to_using_hs(kvreg);
 
-	set_krait_ldo_uv(kvreg, kvreg->uV);
+	set_krait_ldo_uv(kvreg, kvreg->uV - kvreg->ldo_delta_uV);
 
 	/*
 	 * enable ldo - note that both LDO and BHS are are supplying voltage to
@@ -349,18 +351,19 @@
 	list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
 		if (!kvreg->online)
 			continue;
-		if (kvreg->uV > kvreg->ldo_threshold_uV
-			 || kvreg->uV > vmax - kvreg->headroom_uV) {
-			rc = switch_to_using_hs(kvreg);
+		if (kvreg->uV <= kvreg->ldo_threshold_uV
+			&& kvreg->uV - kvreg->ldo_delta_uV + kvreg->headroom_uV
+				<= vmax) {
+			rc = switch_to_using_ldo(kvreg);
 			if (rc < 0) {
-				pr_err("could not switch %s to hs rc = %d\n",
+				pr_err("could not switch %s to ldo rc = %d\n",
 							kvreg->name, rc);
 				return rc;
 			}
 		} else {
-			rc = switch_to_using_ldo(kvreg);
+			rc = switch_to_using_hs(kvreg);
 			if (rc < 0) {
-				pr_err("could not switch %s to ldo rc = %d\n",
+				pr_err("could not switch %s to hs rc = %d\n",
 							kvreg->name, rc);
 				return rc;
 			}
@@ -781,7 +784,10 @@
 #define LDO_UV_MAX		750000
 
 #define LDO_TH_MIN		600000
-#define LDO_TH_MAX		800000
+#define LDO_TH_MAX		900000
+
+#define LDO_DELTA_MIN		10000
+#define LDO_DELTA_MAX		100000
 
 static int __devinit krait_power_probe(struct platform_device *pdev)
 {
@@ -790,6 +796,7 @@
 	struct regulator_init_data *init_data = pdev->dev.platform_data;
 	int rc = 0;
 	int headroom_uV, retention_uV, ldo_default_uV, ldo_threshold_uV;
+	int ldo_delta_uV;
 
 	/* Initialize the pmic gang if it hasn't been initialized already */
 	if (the_gang == NULL) {
@@ -865,6 +872,19 @@
 					ldo_threshold_uV);
 			return -EINVAL;
 		}
+
+		rc = of_property_read_u32(pdev->dev.of_node,
+					"qcom,ldo-delta-voltage",
+					&ldo_delta_uV);
+		if (rc < 0) {
+			pr_err("ldo-delta-voltage missing rc=%d\n", rc);
+			return rc;
+		}
+		if (!is_between(LDO_DELTA_MIN, LDO_DELTA_MAX, ldo_delta_uV)) {
+			pr_err("bad ldo-delta-voltage = %d specified\n",
+					ldo_delta_uV);
+			return -EINVAL;
+		}
 	}
 
 	if (!init_data) {
@@ -916,6 +936,7 @@
 	kvreg->retention_uV	= retention_uV;
 	kvreg->ldo_default_uV	= ldo_default_uV;
 	kvreg->ldo_threshold_uV = ldo_threshold_uV;
+	kvreg->ldo_delta_uV	= ldo_delta_uV;
 
 	platform_set_drvdata(pdev, kvreg);