summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2016-08-23 09:08:52 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2016-08-23 09:08:52 -0700
commite97b6a0e0217f7c072fdad6c50673cd7a64348e1 (patch)
tree1cb64082c6926ce5734bdcbe45658f9965f26a59
parentc605e110ab18604981481a7b502da54640b620bc (diff)
parenta60cb501e00ffc540b803fc29f85f601e0015822 (diff)
Merge "regulator: cprh-kbss-regulator: support the force highest corner fuse"
-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 1c444d6d2607..083459f96ac4 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
*/
@@ -301,6 +311,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",
@@ -485,6 +507,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.
@@ -1201,6 +1271,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",