summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOsvaldo Banuelos <osvaldob@codeaurora.org>2016-08-05 13:56:17 -0700
committerOsvaldo Banuelos <osvaldob@codeaurora.org>2016-08-05 17:08:00 -0700
commita60cb501e00ffc540b803fc29f85f601e0015822 (patch)
tree4f3f89727622a505dc3678052126300618a8c1f1
parent28352998dee80f33641dd7b28479350bd480b823 (diff)
regulator: cprh-kbss-regulator: support the force highest corner fuse
Add support for the MSMCOBALT force highest corner fuse. This fuse is set on parts which can only operate consistently when the highest corner's voltage is applied to all of the lower corners. CRs-Fixed: 1051261 Change-Id: I442e87e780a790d0f00aa62bc0534b6f017fc02c Signed-off-by: Osvaldo Banuelos <osvaldob@codeaurora.org>
-rw-r--r--drivers/regulator/cprh-kbss-regulator.c77
1 files changed, 77 insertions, 0 deletions
diff --git a/drivers/regulator/cprh-kbss-regulator.c b/drivers/regulator/cprh-kbss-regulator.c
index dfdd6921fed5..eb235d0f43cc 100644
--- a/drivers/regulator/cprh-kbss-regulator.c
+++ b/drivers/regulator/cprh-kbss-regulator.c
@@ -51,6 +51,9 @@
* @speed_bin: Application processor speed bin fuse parameter value for
* the given chip
* @cpr_fusing_rev: CPR fusing revision fuse parameter value
+ * @force_highest_corner: Flag indicating that all corners must operate
+ * at the voltage of the highest corner. This is
+ * applicable to MSMCOBALT only.
*
* This struct holds the values for all of the fuses read from memory.
*/
@@ -61,6 +64,7 @@ struct cprh_msmcobalt_kbss_fuses {
u64 quot_offset[MSMCOBALT_KBSS_FUSE_CORNERS];
u64 speed_bin;
u64 cpr_fusing_rev;
+ u64 force_highest_corner;
};
/*
@@ -181,6 +185,12 @@ static const struct cpr3_fuse_param msmcobalt_kbss_speed_bin_param[] = {
{},
};
+static const struct cpr3_fuse_param
+msmcobalt_cpr_force_highest_corner_param[] = {
+ {100, 45, 45},
+ {},
+};
+
/*
* Open loop voltage fuse reference voltages in microvolts for MSMCOBALT v1
*/
@@ -289,6 +299,18 @@ static int cprh_msmcobalt_kbss_read_fuse_data(struct cpr3_regulator *vreg)
}
+ rc = cpr3_read_fuse_param(base,
+ msmcobalt_cpr_force_highest_corner_param,
+ &fuse->force_highest_corner);
+ if (rc) {
+ cpr3_err(vreg, "Unable to read CPR force highest corner fuse, rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ if (fuse->force_highest_corner)
+ cpr3_info(vreg, "Fusing requires all operation at the highest corner\n");
+
vreg->fuse_combo = fuse->cpr_fusing_rev + 8 * fuse->speed_bin;
if (vreg->fuse_combo >= CPRH_MSMCOBALT_KBSS_FUSE_COMBO_COUNT) {
cpr3_err(vreg, "invalid CPR fuse combo = %d found\n",
@@ -464,6 +486,54 @@ done:
}
/**
+ * cprh_msmcobalt_partial_binning_override() - override the voltage and quotient
+ * settings for low corners based upon special partial binning
+ * fuse values
+ *
+ * @vreg: Pointer to the CPR3 regulator
+ *
+ * Some parts are not able to operate at low voltages. The force highest
+ * corner fuse specifies if a given part must operate with voltages
+ * corresponding to the highest corner.
+ *
+ * Return: 0 on success, errno on failure
+ */
+static int cprh_msmcobalt_partial_binning_override(struct cpr3_regulator *vreg)
+{
+ struct cprh_msmcobalt_kbss_fuses *fuse = vreg->platform_fuses;
+ struct cpr3_corner *corner;
+ struct cpr4_sdelta *sdelta;
+ int i;
+ u32 proc_freq;
+
+ if (fuse->force_highest_corner) {
+ cpr3_info(vreg, "overriding CPR parameters for corners 0 to %d with quotients and voltages of corner %d\n",
+ vreg->corner_count - 2, vreg->corner_count - 1);
+ corner = &vreg->corner[vreg->corner_count - 1];
+ for (i = 0; i < vreg->corner_count - 1; i++) {
+ proc_freq = vreg->corner[i].proc_freq;
+ sdelta = vreg->corner[i].sdelta;
+ if (sdelta) {
+ if (sdelta->table)
+ devm_kfree(vreg->thread->ctrl->dev,
+ sdelta->table);
+ if (sdelta->boost_table)
+ devm_kfree(vreg->thread->ctrl->dev,
+ sdelta->boost_table);
+ devm_kfree(vreg->thread->ctrl->dev,
+ sdelta);
+ }
+ vreg->corner[i] = *corner;
+ vreg->corner[i].proc_freq = proc_freq;
+ }
+
+ return 0;
+ }
+
+ return 0;
+};
+
+/**
* cprh_kbss_parse_core_count_temp_adj_properties() - load device tree
* properties associated with per-corner-band and temperature
* voltage adjustments.
@@ -1180,6 +1250,13 @@ static int cprh_kbss_init_regulator(struct cpr3_regulator *vreg)
return -EINVAL;
}
+ rc = cprh_msmcobalt_partial_binning_override(vreg);
+ if (rc) {
+ cpr3_err(vreg, "unable to override CPR parameters based on partial binning fuse values, rc=%d\n",
+ rc);
+ return rc;
+ }
+
rc = cprh_kbss_apm_crossover_as_corner(vreg);
if (rc) {
cpr3_err(vreg, "unable to introduce APM voltage crossover corner, rc=%d\n",