regulator: cpr4: Add miscellaneous fuse based voltage adjustments
Apply voltage adjustments for required voltage corners based on different values of selected miscellaneous fuse bits. Apply the adjustments to both open-loop voltages and closed-loop target quotients. CRs-Fixed: 982984 Change-Id: Ic45949afc8445d35c245434a7f51e4859a5978ad Signed-off-by: Tirupathi Reddy <tirupath@codeaurora.org>
This commit is contained in:
parent
7f3712ee81
commit
0dc93b15a8
2 changed files with 178 additions and 1 deletions
|
@ -348,6 +348,27 @@ APSS specific properties:
|
|||
regardless of the fuse combination and speed bin found
|
||||
on a given chip.
|
||||
|
||||
- qcom,cpr-misc-fuse-voltage-adjustment
|
||||
Usage: optional
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: A grouping of integer tuple lists where each tuple defines
|
||||
the voltage adjustments in microvolts for each voltage
|
||||
corner in order from lowest to highest. This adjustment is
|
||||
applied to both open-loop and closed-loop voltages.
|
||||
|
||||
Each tuple list must contain a number of tuples equal to
|
||||
2 to the power of the number of bits selected for misc
|
||||
voltage adj fuse definition. For MSMTITANIUM the tuple
|
||||
list must contain 2 tuples for the 1-bit misc fuse.
|
||||
Tuples in a list should be specified in ascending order
|
||||
according to the misc fuse value assuming that the fuse
|
||||
is treated like an unsigned integer.
|
||||
|
||||
The tuple list grouping must contain qcom,cpr-speed-bins
|
||||
number of tuple lists in which case the lists are matched to
|
||||
speed bins 1-to-1 or exactly 1 list which is used regardless
|
||||
of the speed bin found on a given chip.
|
||||
|
||||
=======
|
||||
Example
|
||||
=======
|
||||
|
@ -422,6 +443,13 @@ apc_cpr: cpr4-ctrl@b018000 {
|
|||
1689600000 1843200000 1958400000
|
||||
2150400000 2208000000>;
|
||||
|
||||
qcom,cpr-misc-fuse-voltage-adjustment =
|
||||
/* Speed bin 0; misc fuse 0..1 */
|
||||
< 0 0 0 0
|
||||
0 0 0 0>,
|
||||
< 0 0 30000 0
|
||||
0 0 0 0>;
|
||||
|
||||
qcom,allow-voltage-interpolation;
|
||||
qcom,allow-quotient-interpolation;
|
||||
qcom,cpr-scaled-open-loop-voltage-as-ceiling;
|
||||
|
|
|
@ -66,6 +66,7 @@ struct cpr4_msmtitanium_apss_fuses {
|
|||
u64 cpr_fusing_rev;
|
||||
u64 boost_cfg;
|
||||
u64 boost_voltage;
|
||||
u64 misc;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -155,6 +156,17 @@ static const struct cpr3_fuse_param msmtitanium_apss_boost_fuse_volt_param[] = {
|
|||
{},
|
||||
};
|
||||
|
||||
static const struct cpr3_fuse_param msmtitanium_misc_fuse_volt_adj_param[] = {
|
||||
{36, 54, 54},
|
||||
{},
|
||||
};
|
||||
|
||||
/*
|
||||
* The number of possible values for misc fuse is
|
||||
* 2^(#bits defined for misc fuse)
|
||||
*/
|
||||
#define MSMTITANIUM_MISC_FUSE_VAL_COUNT BIT(1)
|
||||
|
||||
/*
|
||||
* Open loop voltage fuse reference voltages in microvolts for MSMTITANIUM
|
||||
*/
|
||||
|
@ -231,6 +243,20 @@ static int cpr4_msmtitanium_apss_read_fuse_data(struct cpr3_regulator *vreg)
|
|||
}
|
||||
cpr3_info(vreg, "CPR fusing revision = %llu\n", fuse->cpr_fusing_rev);
|
||||
|
||||
rc = cpr3_read_fuse_param(base, msmtitanium_misc_fuse_volt_adj_param,
|
||||
&fuse->misc);
|
||||
if (rc) {
|
||||
cpr3_err(vreg, "Unable to read misc voltage adjustment fuse, rc=%d\n",
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
cpr3_info(vreg, "CPR misc fuse value = %llu\n", fuse->misc);
|
||||
if (fuse->misc >= MSMTITANIUM_MISC_FUSE_VAL_COUNT) {
|
||||
cpr3_err(vreg, "CPR misc fuse value = %llu, should be < %lu\n",
|
||||
fuse->misc, MSMTITANIUM_MISC_FUSE_VAL_COUNT);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < MSMTITANIUM_APSS_FUSE_CORNERS; i++) {
|
||||
rc = cpr3_read_fuse_param(base,
|
||||
msmtitanium_apss_init_voltage_param[i],
|
||||
|
@ -324,6 +350,78 @@ static int cpr4_apss_parse_corner_data(struct cpr3_regulator *vreg)
|
|||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* cpr4_apss_parse_misc_fuse_voltage_adjustments() - fill an array from a
|
||||
* portion of the voltage adjustments specified based on
|
||||
* miscellaneous fuse bits.
|
||||
* @vreg: Pointer to the CPR3 regulator
|
||||
* @volt_adjust: Voltage adjustment output data array which must be
|
||||
* of size vreg->corner_count
|
||||
*
|
||||
* cpr3_parse_common_corner_data() must be called for vreg before this function
|
||||
* is called so that speed bin size elements are initialized.
|
||||
*
|
||||
* Two formats are supported for the device tree property:
|
||||
* 1. Length == tuple_list_size * vreg->corner_count
|
||||
* (reading begins at index 0)
|
||||
* 2. Length == tuple_list_size * vreg->speed_bin_corner_sum
|
||||
* (reading begins at index tuple_list_size * vreg->speed_bin_offset)
|
||||
*
|
||||
* Here, tuple_list_size is the number of possible values for misc fuse.
|
||||
* All other property lengths are treated as errors.
|
||||
*
|
||||
* Return: 0 on success, errno on failure
|
||||
*/
|
||||
static int cpr4_apss_parse_misc_fuse_voltage_adjustments(
|
||||
struct cpr3_regulator *vreg, u32 *volt_adjust)
|
||||
{
|
||||
struct device_node *node = vreg->of_node;
|
||||
struct cpr4_msmtitanium_apss_fuses *fuse = vreg->platform_fuses;
|
||||
int tuple_list_size = MSMTITANIUM_MISC_FUSE_VAL_COUNT;
|
||||
int i, offset, rc, len = 0;
|
||||
const char *prop_name = "qcom,cpr-misc-fuse-voltage-adjustment";
|
||||
|
||||
if (!of_find_property(node, prop_name, &len)) {
|
||||
cpr3_err(vreg, "property %s is missing\n", prop_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (len == tuple_list_size * vreg->corner_count * sizeof(u32)) {
|
||||
offset = 0;
|
||||
} else if (vreg->speed_bin_corner_sum > 0 &&
|
||||
len == tuple_list_size * vreg->speed_bin_corner_sum
|
||||
* sizeof(u32)) {
|
||||
offset = tuple_list_size * vreg->speed_bin_offset
|
||||
+ fuse->misc * vreg->corner_count;
|
||||
} else {
|
||||
if (vreg->speed_bin_corner_sum > 0)
|
||||
cpr3_err(vreg, "property %s has invalid length=%d, should be %zu or %zu\n",
|
||||
prop_name, len,
|
||||
tuple_list_size * vreg->corner_count
|
||||
* sizeof(u32),
|
||||
tuple_list_size * vreg->speed_bin_corner_sum
|
||||
* sizeof(u32));
|
||||
else
|
||||
cpr3_err(vreg, "property %s has invalid length=%d, should be %zu\n",
|
||||
prop_name, len,
|
||||
tuple_list_size * vreg->corner_count
|
||||
* sizeof(u32));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < vreg->corner_count; i++) {
|
||||
rc = of_property_read_u32_index(node, prop_name, offset + i,
|
||||
&volt_adjust[i]);
|
||||
if (rc) {
|
||||
cpr3_err(vreg, "error reading property %s, rc=%d\n",
|
||||
prop_name, rc);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* cpr4_msmtitanium_apss_calculate_open_loop_voltages() - calculate the open-loop
|
||||
* voltage for each corner of a CPR3 regulator
|
||||
|
@ -349,7 +447,7 @@ static int cpr4_msmtitanium_apss_calculate_open_loop_voltages(
|
|||
int i, j, rc = 0;
|
||||
bool allow_interpolation;
|
||||
u64 freq_low, volt_low, freq_high, volt_high;
|
||||
int *fuse_volt;
|
||||
int *fuse_volt, *misc_adj_volt;
|
||||
int *fmax_corner;
|
||||
|
||||
fuse_volt = kcalloc(vreg->fuse_corner_count, sizeof(*fuse_volt),
|
||||
|
@ -445,8 +543,34 @@ done:
|
|||
if (rc)
|
||||
cpr3_err(vreg, "open-loop voltage adjustment failed, rc=%d\n",
|
||||
rc);
|
||||
|
||||
if (of_find_property(node,
|
||||
"qcom,cpr-misc-fuse-voltage-adjustment",
|
||||
NULL)) {
|
||||
misc_adj_volt = kcalloc(vreg->corner_count,
|
||||
sizeof(*misc_adj_volt), GFP_KERNEL);
|
||||
if (!misc_adj_volt) {
|
||||
rc = -ENOMEM;
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
rc = cpr4_apss_parse_misc_fuse_voltage_adjustments(vreg,
|
||||
misc_adj_volt);
|
||||
if (rc) {
|
||||
cpr3_err(vreg, "qcom,cpr-misc-fuse-voltage-adjustment reading failed, rc=%d\n",
|
||||
rc);
|
||||
kfree(misc_adj_volt);
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
for (i = 0; i < vreg->corner_count; i++)
|
||||
vreg->corner[i].open_loop_volt
|
||||
+= misc_adj_volt[i];
|
||||
kfree(misc_adj_volt);
|
||||
}
|
||||
}
|
||||
|
||||
_exit:
|
||||
kfree(fuse_volt);
|
||||
kfree(fmax_corner);
|
||||
return rc;
|
||||
|
@ -525,6 +649,7 @@ static int cpr4_msmtitanium_apss_calculate_target_quotients(
|
|||
int i, j, fuse_corner, quot_adjust;
|
||||
int *fmax_corner;
|
||||
int *volt_adjust, *volt_adjust_fuse, *ro_scale;
|
||||
int *voltage_adj_misc;
|
||||
|
||||
/* Log fused quotient values for debugging purposes. */
|
||||
cpr3_info(vreg, "fused LowSVS: quot[%2llu]=%4llu\n",
|
||||
|
@ -567,6 +692,30 @@ static int cpr4_msmtitanium_apss_calculate_target_quotients(
|
|||
goto done;
|
||||
}
|
||||
|
||||
if (of_find_property(vreg->of_node,
|
||||
"qcom,cpr-misc-fuse-voltage-adjustment", NULL)) {
|
||||
voltage_adj_misc = kcalloc(vreg->corner_count,
|
||||
sizeof(*voltage_adj_misc), GFP_KERNEL);
|
||||
if (!voltage_adj_misc) {
|
||||
rc = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
rc = cpr4_apss_parse_misc_fuse_voltage_adjustments(vreg,
|
||||
voltage_adj_misc);
|
||||
if (rc) {
|
||||
cpr3_err(vreg, "qcom,cpr-misc-fuse-voltage-adjustment reading failed, rc=%d\n",
|
||||
rc);
|
||||
kfree(voltage_adj_misc);
|
||||
goto done;
|
||||
}
|
||||
|
||||
for (i = 0; i < vreg->corner_count; i++)
|
||||
volt_adjust[i] += voltage_adj_misc[i];
|
||||
|
||||
kfree(voltage_adj_misc);
|
||||
}
|
||||
|
||||
if (!allow_interpolation) {
|
||||
/* Use fused target quotients for lower frequencies. */
|
||||
return cpr4_msmtitanium_apss_set_no_interpolation_quotients(
|
||||
|
|
Loading…
Add table
Reference in a new issue