diff options
| author | Linux Build Service Account <lnxbuild@localhost> | 2016-08-23 09:08:52 -0700 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2016-08-23 09:08:52 -0700 |
| commit | e97b6a0e0217f7c072fdad6c50673cd7a64348e1 (patch) | |
| tree | 1cb64082c6926ce5734bdcbe45658f9965f26a59 | |
| parent | c605e110ab18604981481a7b502da54640b620bc (diff) | |
| parent | a60cb501e00ffc540b803fc29f85f601e0015822 (diff) | |
Merge "regulator: cprh-kbss-regulator: support the force highest corner fuse"
| -rw-r--r-- | drivers/regulator/cprh-kbss-regulator.c | 77 |
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", |
