summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorDavid Collins <collinsd@codeaurora.org>2015-12-08 17:36:37 -0800
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 21:23:17 -0700
commit5cf7daa23d0b41a2a840cd94ca32502476b9a9d4 (patch)
tree0ade5cf2598cf641fdcba734716466ab06b4a6e4 /drivers
parent70dcea8217e4525c8aacf4502a4c9d65b8cc5b46 (diff)
regulator: cpr3-regulator: adjust voltage limits based upon aging results
Adjust the floor, ceiling, and open-loop voltages for each corner of each CPR3 regulator based upon aging measurements. This allows the fixed open-loop voltage adjustment to be reduced since it no longer has to account for the maximum possible aging adjustment. This in turn leads to more situations where LDO mode may be used for the HMSS CPR3 regulators since the LDO must always operate at the open-loop voltage. Change-Id: Iaca0ed4b51f258656b5c44dc58f7361814ca3af7 CRs-Fixed: 949622 Signed-off-by: David Collins <collinsd@codeaurora.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/regulator/cpr3-regulator.c67
-rw-r--r--drivers/regulator/cpr3-regulator.h28
-rw-r--r--drivers/regulator/cpr3-util.c15
3 files changed, 101 insertions, 9 deletions
diff --git a/drivers/regulator/cpr3-regulator.c b/drivers/regulator/cpr3-regulator.c
index 5c028d51fdc0..309ec4c1e745 100644
--- a/drivers/regulator/cpr3-regulator.c
+++ b/drivers/regulator/cpr3-regulator.c
@@ -3505,7 +3505,8 @@ cleanup:
}
/**
- * cpr3_regulator_readjust_quotients() - readjust the target quotients for the
+ * cpr3_regulator_readjust_volt_and_quot() - readjust the target quotients as
+ * well as the floor, ceiling, and open-loop voltages for the
* regulator by removing the old adjustment and adding the new one
* @vreg: Pointer to the CPR3 regulator
* @old_adjust_volt: Old aging adjustment voltage in microvolts
@@ -3513,12 +3514,14 @@ cleanup:
*
* Also reset the cached closed loop voltage (last_volt) to equal the open-loop
* voltage for each corner.
+ *
+ * Return: None
*/
-static void cpr3_regulator_readjust_quotients(struct cpr3_regulator *vreg,
+static void cpr3_regulator_readjust_volt_and_quot(struct cpr3_regulator *vreg,
int old_adjust_volt, int new_adjust_volt)
{
unsigned long long temp;
- int i, j, old_volt, new_volt;
+ int i, j, old_volt, new_volt, rounded_volt;
if (!vreg->aging_allowed)
return;
@@ -3548,14 +3551,34 @@ static void cpr3_regulator_readjust_quotients(struct cpr3_regulator *vreg,
old_volt);
}
}
+
+ rounded_volt = CPR3_ROUND(new_volt,
+ vreg->thread->ctrl->step_volt);
+
+ if (!vreg->aging_allow_open_loop_adj)
+ rounded_volt = 0;
+
+ vreg->corner[i].ceiling_volt
+ = vreg->corner[i].unaged_ceiling_volt + rounded_volt;
+ vreg->corner[i].ceiling_volt = min(vreg->corner[i].ceiling_volt,
+ vreg->corner[i].abs_ceiling_volt);
+ vreg->corner[i].floor_volt
+ = vreg->corner[i].unaged_floor_volt + rounded_volt;
+ vreg->corner[i].floor_volt = min(vreg->corner[i].floor_volt,
+ vreg->corner[i].ceiling_volt);
+ vreg->corner[i].open_loop_volt
+ = vreg->corner[i].unaged_open_loop_volt + rounded_volt;
+ vreg->corner[i].open_loop_volt
+ = min(vreg->corner[i].open_loop_volt,
+ vreg->corner[i].ceiling_volt);
+
vreg->corner[i].last_volt = vreg->corner[i].open_loop_volt;
- cpr3_debug(vreg, "corner %d: applying %d uV closed-loop voltage margin adjustment\n",
- i, new_volt);
+ cpr3_debug(vreg, "corner %d: applying %d uV closed-loop and %d uV open-loop voltage margin adjustment\n",
+ i, new_volt, rounded_volt);
}
}
-
/**
* cpr3_regulator_set_aging_ref_adjustment() - adjust target quotients for the
* regulators managed by this CPR controller to account for aging
@@ -3574,7 +3597,7 @@ static void cpr3_regulator_set_aging_ref_adjustment(
for (i = 0; i < ctrl->thread_count; i++) {
for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
- cpr3_regulator_readjust_quotients(
+ cpr3_regulator_readjust_volt_and_quot(
&ctrl->thread[i].vreg[j],
ctrl->aging_ref_adjust_volt,
ref_adjust_volt);
@@ -5586,10 +5609,13 @@ static int cpr3_regulator_init_ctrl_data(struct cpr3_controller *ctrl)
static int cpr3_regulator_init_vreg_data(struct cpr3_regulator *vreg)
{
int i, j;
+ bool init_aging;
vreg->current_corner = CPR3_REGULATOR_CORNER_INVALID;
vreg->last_closed_loop_corner = CPR3_REGULATOR_CORNER_INVALID;
+ init_aging = vreg->aging_allowed && vreg->thread->ctrl->aging_required;
+
for (i = 0; i < vreg->corner_count; i++) {
vreg->corner[i].last_volt = vreg->corner[i].open_loop_volt;
vreg->corner[i].irq_en = CPR3_IRQ_UP | CPR3_IRQ_DOWN;
@@ -5599,6 +5625,33 @@ static int cpr3_regulator_init_vreg_data(struct cpr3_regulator *vreg)
if (vreg->corner[i].target_quot[j] == 0)
vreg->corner[i].ro_mask |= BIT(j);
}
+
+ if (init_aging) {
+ vreg->corner[i].unaged_floor_volt
+ = vreg->corner[i].floor_volt;
+ vreg->corner[i].unaged_ceiling_volt
+ = vreg->corner[i].ceiling_volt;
+ vreg->corner[i].unaged_open_loop_volt
+ = vreg->corner[i].open_loop_volt;
+ }
+
+ if (vreg->aging_allowed) {
+ if (vreg->corner[i].unaged_floor_volt <= 0) {
+ cpr3_err(vreg, "invalid unaged_floor_volt[%d] = %d\n",
+ i, vreg->corner[i].unaged_floor_volt);
+ return -EINVAL;
+ }
+ if (vreg->corner[i].unaged_ceiling_volt <= 0) {
+ cpr3_err(vreg, "invalid unaged_ceiling_volt[%d] = %d\n",
+ i, vreg->corner[i].unaged_ceiling_volt);
+ return -EINVAL;
+ }
+ if (vreg->corner[i].unaged_open_loop_volt <= 0) {
+ cpr3_err(vreg, "invalid unaged_open_loop_volt[%d] = %d\n",
+ i, vreg->corner[i].unaged_open_loop_volt);
+ return -EINVAL;
+ }
+ }
}
if (vreg->aging_allowed && vreg->corner[vreg->aging_corner].ceiling_volt
diff --git a/drivers/regulator/cpr3-regulator.h b/drivers/regulator/cpr3-regulator.h
index d7729641fcf6..111d362a9384 100644
--- a/drivers/regulator/cpr3-regulator.h
+++ b/drivers/regulator/cpr3-regulator.h
@@ -100,6 +100,16 @@ struct cpr4_sdelta {
* microvolts
* @last_volt: Last known settled CPR closed-loop voltage which is used
* when switching to a new corner
+ * @abs_ceiling_volt: The absolute CPR closed-loop ceiling voltage in
+ * microvolts. This is used to limit the ceiling_volt
+ * value when it is increased as a result of aging
+ * adjustment.
+ * @unaged_floor_volt: The CPR closed-loop floor voltage in microvolts before
+ * any aging adjustment is performed
+ * @unaged_ceiling_volt: The CPR closed-loop ceiling voltage in microvolts
+ * before any aging adjustment is performed
+ * @unaged_open_loop_volt: The CPR open-loop voltage (i.e. initial voltage) in
+ * microvolts before any aging adjusment is performed
* @system_volt: The system-supply voltage in microvolts or corners or
* levels
* @mem_acc_volt: The mem-acc-supply voltage in corners
@@ -136,7 +146,11 @@ struct cpr4_sdelta {
*
* The value of last_volt is initialized inside of the cpr3_regulator_register()
* call with the open_loop_volt value. It can later be updated to the settled
- * VDD supply voltage.
+ * VDD supply voltage. The values for unaged_floor_volt, unaged_ceiling_volt,
+ * and unaged_open_loop_volt are initialized inside of cpr3_regulator_register()
+ * if ctrl->aging_required == true. These three values must be pre-initialized
+ * if cpr3_regulator_register() is called with ctrl->aging_required == false and
+ * ctrl->aging_succeeded == true.
*
* The values of ro_mask and irq_en are initialized inside of the
* cpr3_regulator_register() call.
@@ -146,6 +160,10 @@ struct cpr3_corner {
int ceiling_volt;
int open_loop_volt;
int last_volt;
+ int abs_ceiling_volt;
+ int unaged_floor_volt;
+ int unaged_ceiling_volt;
+ int unaged_open_loop_volt;
int system_volt;
int mem_acc_volt;
u32 proc_freq;
@@ -277,6 +295,13 @@ struct cprh_corner_band {
* @aging_allowed: Boolean defining if CPR aging adjustments are allowed
* for this CPR3 regulator given the fuse combo of the
* device
+ * @aging_allow_open_loop_adj: Boolean defining if the open-loop voltage of each
+ * corner of this regulator should be adjusted as a result
+ * of an aging measurement. This flag can be set to false
+ * when the open-loop voltage adjustments have been
+ * specified such that they include the maximum possible
+ * aging adjustment. This flag is only used if
+ * aging_allowed == true.
* @aging_corner: The corner that should be configured for this regulator
* when an aging measurement is performed.
* @aging_max_adjust_volt: The maximum aging voltage margin in microvolts that
@@ -342,6 +367,7 @@ struct cpr3_regulator {
bool vreg_enabled;
bool aging_allowed;
+ bool aging_allow_open_loop_adj;
int aging_corner;
int aging_max_adjust_volt;
diff --git a/drivers/regulator/cpr3-util.c b/drivers/regulator/cpr3-util.c
index d208e8a10ced..255e585f02a3 100644
--- a/drivers/regulator/cpr3-util.c
+++ b/drivers/regulator/cpr3-util.c
@@ -695,9 +695,11 @@ int cpr3_parse_common_corner_data(struct cpr3_regulator *vreg)
1, temp);
if (rc)
goto free_temp;
- for (i = 0; i < vreg->corner_count; i++)
+ for (i = 0; i < vreg->corner_count; i++) {
vreg->corner[i].ceiling_volt
= CPR3_ROUND(temp[i], ctrl->step_volt);
+ vreg->corner[i].abs_ceiling_volt = vreg->corner[i].ceiling_volt;
+ }
rc = cpr3_parse_corner_array_property(vreg, "qcom,cpr-voltage-floor",
1, temp);
@@ -807,6 +809,17 @@ int cpr3_parse_common_corner_data(struct cpr3_regulator *vreg)
vreg->aging_allowed = aging_allowed;
}
+ if (of_find_property(vreg->of_node,
+ "qcom,allow-aging-open-loop-voltage-adjustment", NULL)) {
+ rc = cpr3_parse_array_property(vreg,
+ "qcom,allow-aging-open-loop-voltage-adjustment",
+ 1, &aging_allowed);
+ if (rc)
+ goto free_temp;
+
+ vreg->aging_allow_open_loop_adj = aging_allowed;
+ }
+
if (vreg->aging_allowed) {
if (ctrl->aging_ref_volt <= 0) {
cpr3_err(ctrl, "qcom,cpr-aging-ref-voltage must be specified\n");