Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9f7091be authored by David Collins's avatar David Collins Committed by Matt Wagantall
Browse files

regulator: cpr3-regulator: add support for voltage adjustment specification



Add support in the cpr3-regulator driver to handle open-loop
voltage and closed-loop voltage adjustments which are specified
in CPR3 thread device tree nodes.  These adjustments can be used
to add or remove voltage margin per-fuse-corner or per-corner.
This ensures stability while also reducing power consumption.

Change-Id: I7248819a282dfaaff672049535f491ee77784de3
Signed-off-by: default avatarDavid Collins <collinsd@codeaurora.org>
parent 311fa89d
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -195,6 +195,23 @@ apcc_cpr: cpr3-ctrl@99e8000 {
			1017600000 1113600000 1190400000 1267200000
			1344000000 1420800000 1459200000>;

		qcom,cpr-ro-scaling-factor =
			<   0    0    0    0 2222 2275 2506 2491
			 2649 2640 2886 2866    0    0    0    0>,
			<   0    0    0    0 2222 2275 2506 2491
			 2649 2640 2886 2866    0    0    0    0>,
			<   0    0    0    0 2222 2275 2506 2491
			 2649 2640 2886 2866    0    0    0    0>,
			<   0    0    0    0 2147 2226 2310 2312
			 2450 2447 2603 2600    0    0    0    0>,
			<   0    0    0    0 1989 2079 2066 2083
			 2193 2201 2283 2296    0    0    0    0>;

		qcom,cpr-open-loop-voltage-fuse-adjustment =
			<0 0 0 0 0>;
		qcom,cpr-closed-loop-voltage-fuse-adjustment =
			<0 0 0 0 0>;

		qcom,allow-voltage-interpolation;
		qcom,allow-quotient-interpolation;
		qcom,cpr-scaled-open-loop-voltage-as-ceiling;
@@ -235,6 +252,23 @@ apcc_cpr: cpr3-ctrl@99e8000 {
			1190400000 1267200000 1344000000 1420800000
			1497600000 1593600000>;

		qcom,cpr-ro-scaling-factor =
			<   0    0    0    0 2212 2273 2517 2506
			 2663 2650 2908 2891    0    0    0    0>,
			<   0    0    0    0 2212 2273 2517 2506
			 2663 2650 2908 2891    0    0    0    0>,
			<   0    0    0    0 2212 2273 2517 2506
			 2663 2650 2908 2891    0    0    0    0>,
			<   0    0    0    0 2152 2237 2321 2337
			 2475 2469 2636 2612    0    0    0    0>,
			<   0    0    0    0 2001 2102 2092 2090
			 2203 2210 2297 2297    0    0    0    0>;

		qcom,cpr-open-loop-voltage-fuse-adjustment =
			<0 0 0 5000 0>;
		qcom,cpr-closed-loop-voltage-fuse-adjustment =
			<0 0 0 20000 0>;

		qcom,allow-voltage-interpolation;
		qcom,allow-quotient-interpolation;
		qcom,cpr-scaled-open-loop-voltage-as-ceiling;
+28 −0
Original line number Diff line number Diff line
@@ -86,6 +86,23 @@ HMSS specific properties:
		    grouping must contain exactly 1 list which is used
		    regardless of the fuse combination found on a given chip.

- qcom,cpr-ro-scaling-factor
	Usage:      required if qcom,cpr-closed-loop-voltage-adjustment is
		    specified
	Value type: <prop-encoded-array>
	Definition: The common definition of this property in cpr3-regulator.txt
		    is accurate for MMSS CPR3 controllers except for this
		    modification:

		    Each tuple list must contain the number of tuples defined in
		    the corresponding element of the qcom,cpr-corners property
		    as opposed to the value of the qcom,cpr-fuse-corners
		    property.

Note that the qcom,cpr-closed-loop-voltage-fuse-adjustment property is not
meaningful for MMSS CPR3 thread nodes since target quotients are not defined in
fuses.

=======
Example
=======
@@ -143,6 +160,17 @@ gfx_cpr: cpr3-ctrl@838000 {
			<0 0 0 0 669 601 0  851 0  905 0 0 0 0 0 0>,
			<0 0 0 0 899 806 0 1084 0 1149 0 0 0 0 0 0>;

		qcom,cpr-ro-scaling-factor =
			<0 0 0 0 2268 2004 0 2408 0 2539 0 0 0 0 0 0>,
			<0 0 0 0 2268 2004 0 2408 0 2539 0 0 0 0 0 0>,
			<0 0 0 0 2268 2004 0 2408 0 2539 0 0 0 0 0 0>,
			<0 0 0 0 2268 2004 0 2408 0 2539 0 0 0 0 0 0>;

		qcom,cpr-open-loop-voltage-fuse-adjustment =
			<35000 0 0 0>;
		qcom,cpr-closed-loop-voltage-adjustment =
			<45000 0 0 0>;

		qcom,allow-voltage-interpolation;
		qcom,cpr-scaled-open-loop-voltage-as-ceiling;
	};
+119 −0
Original line number Diff line number Diff line
@@ -285,6 +285,125 @@ Platform independent properties:
		    the interpolated open-loop voltage for each corner as the
		    CPR ceiling voltage for each corner.

- qcom,cpr-open-loop-voltage-fuse-adjustment
	Usage:      optional
	Value type: <prop-encoded-array>
	Definition: A list of integer tuples which each define the open-loop
		    voltage adjustment in microvolts for each fused voltage
		    corner in order from lowest to highest.  This adjustment is
		    applied to the values read from fuses before the values are
		    used in interpolation for intermediate corners.

		    The list must contain either qcom,cpr-fuse-combos number of
		    tuples in which case the tuples are matched to fuse
		    combinations 1-to-1 or the list must contain exactly 1 tuple
		    which is used regardless of the fuse combination found on a
		    given chip.

		    Each tuple must have a number of elements equal to the value
		    of the qcom,cpr-fuse-corners property.

		    The open-loop voltage for a given fuse corner corresponds to
		    the voltage that is safe to use under all circumstances.
		    It is used as a starting voltage for CPR and may also be
		    specified as a ceiling voltage for CPR scaling.

- qcom,cpr-open-loop-voltage-adjustment
	Usage:      optional
	Value type: <prop-encoded-array>
	Definition: A list of integer tuples which each define the open-loop
		    voltage adjustment in microvolts for each voltage corner in
		    order from lowest to highest.  This adjustment is applied to
		    the open-loop voltage values after they have been
		    interpolated for intermediate corners.

		    The list must contain either qcom,cpr-fuse-combos number of
		    tuples in which case the tuples are matched to fuse
		    combinations 1-to-1 or the list must contain exactly 1 tuple
		    which is used regardless of the fuse combination found on a
		    given chip.

		    Each tuple must be of the length defined in the
		    corresponding element of the qcom,cpr-corners property.  A
		    single tuple may only be specified if all of the corner
		    counts in qcom,cpr-corners are the same.

- qcom,cpr-closed-loop-voltage-fuse-adjustment
	Usage:      optional
	Value type: <prop-encoded-array>
	Definition: A list of integer tuples which each define the closed-loop
		    voltage adjustment in microvolts for each fused voltage
		    corner in order from lowest to highest.  This adjustment is
		    applied to the values read from fuses before the values are
		    used in interpolation for intermediate corners.

		    The list must contain either qcom,cpr-fuse-combos number of
		    tuples in which case the tuples are matched to fuse
		    combinations 1-to-1 or the list must contain exactly 1 tuple
		    which is used regardless of the fuse combination found on a
		    given chip.

		    Each tuple must have a number of elements equal to the value
		    of the qcom,cpr-fuse-corners property.
		    The qcom,cpr-ro-scaling-factor property must be specified
		    in order to utilize this property.

		    The closed-loop voltage for a given fuse corner corresponds
		    to the voltage that the CPR controller settles the VDD
		    supply rail to based upon the programmed CPR target
		    quotients and the current silicon conditions.

- qcom,cpr-closed-loop-voltage-adjustment
	Usage:      optional
	Value type: <prop-encoded-array>
	Definition: A list of integer tuples which each define the closed-loop
		    voltage adjustment in microvolts for each voltage corner in
		    order from lowest to highest.  This adjustment is applied to
		    target quotient values after they have been interpolated
		    for intermediate corners.

		    The list must contain either qcom,cpr-fuse-combos number of
		    tuples in which case the tuples are matched to fuse
		    combinations 1-to-1 or the list must contain exactly 1 tuple
		    which is used regardless of the fuse combination found on a
		    given chip.

		    Each tuple must be of the length defined in the
		    corresponding element of the qcom,cpr-corners property.  A
		    single tuple may only be specified if all of the corner
		    counts in qcom,cpr-corners are the same.  The
		    qcom,cpr-ro-scaling-factor property must be specified in
		    order to utilize this property.

- qcom,cpr-ro-scaling-factor
	Usage:      required if qcom,cpr-closed-loop-voltage-fuse-adjustment
		    or qcom,cpr-closed-loop-voltage-adjustment is specified
	Value type: <prop-encoded-array>
	Definition: A grouping of integer tuple lists.  Each tuple defines the
		    CPR ring oscillator (RO) scaling factor with units of QUOT/V
		    for each RO for a given fuse corner.  Since CPR3 supports
		    exactly 16 ROs, each tuple must contain 16 elements
		    corresponding to RO0 through RO15 in order.  If a given RO
		    is unused for a fuse corner, then its scaling factor may be
		    specified as 0.

		    Each tuple list must contain the number of tuples defined in
		    the qcom,cpr-fuse-corners property.  The tuples in a given
		    list are ordered from the lowest fuse corner to the highest
		    fuse corner.

		    The tuple list grouping must contain either
		    qcom,cpr-fuse-combos number of tuple lists in which case the
		    lists are matched to fuse combinations 1-to-1 or the
		    grouping must contain exactly 1 list which is used
		    regardless of the fuse combination found on a given chip.

		    The target quotient adjustment to apply for each RO of a
		    given corner is determined by multiplying the adjustment
		    value in qcom,cpr-closed-loop-voltage-fuse-adjustment or
		    qcom,cpr-closed-loop-voltage-adjustment by the relevant RO
		    scaling factor in this property.

All properties specified within the core regulator framework can also be used in
second level nodes.  These bindings can be found in:
Documentation/devicetree/bindings/regulator/regulator.txt.
+227 −24
Original line number Diff line number Diff line
@@ -461,16 +461,19 @@ static int cpr3_msm8996_hmss_read_fuse_data(struct cpr3_thread *thread)
 * cpr3_hmss_parse_corner_data() - parse HMSS corner data from device tree
 *				properties of the thread's device node
 * @thread:		Pointer to the CPR3 thread
 * @corner_sum:		Pointer which is output with the sum of the corner
 *			counts across all fuse combos
 * @combo_offset:	Pointer which is output with the array offset for the
 *			selected fuse combo
 *
 * Return: 0 on success, errno on failure
 */
static int cpr3_hmss_parse_corner_data(struct cpr3_thread *thread)
static int cpr3_hmss_parse_corner_data(struct cpr3_thread *thread,
			int *corner_sum, int *combo_offset)
{
	int corner_sum = 0;
	int combo_offset = 0;
	int rc;

	rc = cpr3_parse_common_corner_data(thread, &corner_sum, &combo_offset);
	rc = cpr3_parse_common_corner_data(thread, corner_sum, combo_offset);
	if (rc) {
		cpr3_err(thread, "error reading corner data, rc=%d\n", rc);
		return rc;
@@ -483,6 +486,8 @@ static int cpr3_hmss_parse_corner_data(struct cpr3_thread *thread)
 * cpr3_msm8996_hmss_calculate_open_loop_voltages() - calculate the open-loop
 *		voltage for each corner of a CPR3 thread
 * @thread:		Pointer to the CPR3 thread
 * @corner_sum:		Sum of the corner counts across all fuse combos
 * @combo_offset:	Array offset for the selected fuse combo
 *
 * If open-loop voltage interpolation is allowed in both device tree and in
 * hardware fuses, then this function calculates the open-loop voltage for a
@@ -497,7 +502,8 @@ static int cpr3_hmss_parse_corner_data(struct cpr3_thread *thread)
 * Return: 0 on success, errno on failure
 */
static int cpr3_msm8996_hmss_calculate_open_loop_voltages(
			struct cpr3_thread *thread)
			struct cpr3_thread *thread, int corner_sum,
			int combo_offset)
{
	struct device_node *node = thread->of_node;
	struct cpr3_msm8996_hmss_fuses *fuse = thread->platform_fuses;
@@ -531,6 +537,13 @@ static int cpr3_msm8996_hmss_calculate_open_loop_voltages(
				fuse_volt[i]);
	}

	rc = cpr3_adjust_fused_open_loop_voltages(thread, fuse_volt);
	if (rc) {
		cpr3_err(thread, "fused open-loop voltage adjustment failed, rc=%d\n",
			rc);
		goto done;
	}

	allow_interpolation = of_property_read_bool(node,
				"qcom,allow-voltage-interpolation");

@@ -604,6 +617,12 @@ done:
		for (i = 0; i < thread->corner_count; i++)
			cpr3_debug(thread, "open-loop[%2d] = %d uV\n", i,
				thread->corner[i].open_loop_volt);

		rc = cpr3_adjust_open_loop_voltages(thread, corner_sum,
			combo_offset);
		if (rc)
			cpr3_err(thread, "open-loop voltage adjustment failed, rc=%d\n",
				rc);
	}

	kfree(fuse_volt);
@@ -682,25 +701,133 @@ static int cpr3_hmss_adjust_voltages_for_apm(struct cpr3_thread *thread)
	return 0;
}

/**
 * cpr3_hmss_parse_closed_loop_voltage_adjustments() - load per-fuse-corner and
 *		per-corner closed-loop adjustment values from device tree
 * @thread:		Pointer to the CPR3 thread
 * @corner_sum:		Sum of the corner counts across all fuse combos
 * @combo_offset:	Array offset for the selected fuse combo
 * @volt_adjust:	Pointer to array which will be filled with the
 *			per-corner closed-loop adjustment voltages
 * @volt_adjust_fuse:	Pointer to array which will be filled with the
 *			per-fuse-corner closed-loop adjustment voltages
 * @ro_scale:		Pointer to array which will be filled with the
 *			per-fuse-corner RO scaling factor values with units of
 *			QUOT/V
 *
 * Return: 0 on success, errno on failure
 */
static int cpr3_hmss_parse_closed_loop_voltage_adjustments(
			struct cpr3_thread *thread, int corner_sum,
			int combo_offset, int *volt_adjust,
			int *volt_adjust_fuse, int *ro_scale)
{
	struct cpr3_msm8996_hmss_fuses *fuse = thread->platform_fuses;
	int i, rc;
	u32 *ro_all_scale;

	if (!of_find_property(thread->of_node,
			"qcom,cpr-closed-loop-voltage-adjustment", NULL)
	    && !of_find_property(thread->of_node,
			"qcom,cpr-closed-loop-voltage-fuse-adjustment", NULL)) {
		/* No adjustment required. */
		return 0;
	} else if (!of_find_property(thread->of_node,
			"qcom,cpr-ro-scaling-factor", NULL)) {
		cpr3_err(thread, "qcom,cpr-ro-scaling-factor is required for closed-loop voltage adjustment, but is missing\n");
		return -EINVAL;
	}

	ro_all_scale = kzalloc(sizeof(*ro_all_scale)
				* thread->fuse_corner_count * CPR3_RO_COUNT,
				GFP_KERNEL);
	if (!ro_all_scale) {
		cpr3_err(thread, "memory allocation failed\n");
		return -ENOMEM;
	}

	rc = cpr3_parse_array_property(thread, "qcom,cpr-ro-scaling-factor",
		thread->fuse_corner_count * CPR3_RO_COUNT,
		thread->fuse_combos_supported * thread->fuse_corner_count
			* CPR3_RO_COUNT,
		thread->fuse_combo * thread->fuse_corner_count * CPR3_RO_COUNT,
		ro_all_scale);
	if (rc) {
		cpr3_err(thread, "could not load RO scaling factors, rc=%d\n",
			rc);
		goto done;
	}

	for (i = 0; i < thread->fuse_corner_count; i++)
		ro_scale[i] = ro_all_scale[i * CPR3_RO_COUNT + fuse->ro_sel[i]];

	if (of_find_property(thread->of_node,
			"qcom,cpr-closed-loop-voltage-fuse-adjustment", NULL)) {
		rc = cpr3_parse_array_property(thread,
			"qcom,cpr-closed-loop-voltage-fuse-adjustment",
			thread->fuse_corner_count,
			thread->fuse_combos_supported
				* thread->fuse_corner_count,
			thread->fuse_combo * thread->fuse_corner_count,
			volt_adjust_fuse);
		if (rc) {
			cpr3_err(thread, "could not load closed-loop fused voltage adjustments, rc=%d\n",
				rc);
			goto done;
		}
	}

	if (of_find_property(thread->of_node,
			"qcom,cpr-closed-loop-voltage-adjustment", NULL)) {
		rc = cpr3_parse_array_property(thread,
			"qcom,cpr-closed-loop-voltage-adjustment",
			thread->corner_count, corner_sum, combo_offset,
			volt_adjust);
		if (rc) {
			cpr3_err(thread, "could not load closed-loop voltage adjustments, rc=%d\n",
				rc);
			goto done;
		}
	}

done:
	kfree(ro_all_scale);
	return rc;
}

/**
 * cpr3_msm8996_hmss_set_no_interpolation_quotients() - use the fused target
 *		quotient values for lower frequencies.
 * @thread:		Pointer to the CPR3 thread
 * @volt_adjust:	Pointer to array of per-corner closed-loop adjustment
 *			voltages
 * @volt_adjust_fuse:	Pointer to array of per-fuse-corner closed-loop
 *			adjustment voltages
 * @ro_scale:		Pointer to array of per-fuse-corner RO scaling factor
 *			values with units of QUOT/V
 *
 * Return: 0 on success, errno on failure
 */
static int cpr3_msm8996_hmss_set_no_interpolation_quotients(
			struct cpr3_thread *thread)
			struct cpr3_thread *thread, int *volt_adjust,
			int *volt_adjust_fuse, int *ro_scale)
{
	struct cpr3_msm8996_hmss_fuses *fuse = thread->platform_fuses;
	u32 quot, ro;
	int quot_adjust;
	int i, fuse_corner;

	for (i = 0; i < thread->corner_count; i++) {
		fuse_corner = thread->corner[i].cpr_fuse_corner;
		quot = fuse->target_quot[fuse_corner];
		quot_adjust = cpr3_quot_adjustment(ro_scale[fuse_corner],
				volt_adjust_fuse[fuse_corner] + volt_adjust[i]);
		ro = fuse->ro_sel[fuse_corner];
		thread->corner[i].target_quot[ro] = quot;
		thread->corner[i].target_quot[ro] = quot + quot_adjust;
		if (quot_adjust)
			cpr3_info(thread, "adjusted corner %d RO%u target quot: %u --> %u (%d uV)\n",
				i, ro, quot, thread->corner[i].target_quot[ro],
				volt_adjust_fuse[fuse_corner] + volt_adjust[i]);
	}

	return 0;
@@ -710,6 +837,8 @@ static int cpr3_msm8996_hmss_set_no_interpolation_quotients(
 * cpr3_msm8996_hmss_calculate_target_quotients() - calculate the CPR target
 *		quotient for each corner of a CPR3 thread
 * @thread:		Pointer to the CPR3 thread
 * @corner_sum:		Sum of the corner counts across all fuse combos
 * @combo_offset:	Array offset for the selected fuse combo
 *
 * If target quotient interpolation is allowed in both device tree and in
 * hardware fuses, then this function calculates the target quotient for a
@@ -724,17 +853,19 @@ static int cpr3_msm8996_hmss_set_no_interpolation_quotients(
 * Return: 0 on success, errno on failure
 */
static int cpr3_msm8996_hmss_calculate_target_quotients(
			struct cpr3_thread *thread)
			struct cpr3_thread *thread, int corner_sum,
			int combo_offset)
{
	struct cpr3_msm8996_hmss_fuses *fuse = thread->platform_fuses;
	int rc;
	bool allow_interpolation;
	u64 freq_low, freq_high;
	u64 freq_low, freq_high, prev_quot;
	u64 *quot_low;
	u64 *quot_high;
	u32 quot, ro;
	int i, j;
	int i, j, fuse_corner, quot_adjust;
	int *fmax_corner;
	int *volt_adjust, *volt_adjust_fuse, *ro_scale;

	/* Log fused quotient values for debugging purposes. */
	cpr3_info(thread, "fused MinSVS: quot[%2llu]=%4llu\n",
@@ -753,23 +884,39 @@ static int cpr3_msm8996_hmss_calculate_target_quotients(
	if (fuse->limitation == MSM8996_CPR_LIMITATION_NO_CPR_OR_INTERPOLATION)
		allow_interpolation = false;

	if (!allow_interpolation) {
		/* Use fused target quotients for lower frequencies. */
		return cpr3_msm8996_hmss_set_no_interpolation_quotients(thread);
	}

	volt_adjust = kzalloc(sizeof(*volt_adjust) * thread->corner_count,
					GFP_KERNEL);
	volt_adjust_fuse = kzalloc(sizeof(*volt_adjust_fuse)
				       * thread->fuse_corner_count, GFP_KERNEL);
	ro_scale = kzalloc(sizeof(*ro_scale) * thread->fuse_corner_count,
					GFP_KERNEL);
	fmax_corner = kzalloc(sizeof(*fmax_corner) * thread->fuse_corner_count,
					GFP_KERNEL);
	quot_low = kzalloc(sizeof(*quot_low) * thread->fuse_corner_count,
					GFP_KERNEL);
	quot_high = kzalloc(sizeof(*quot_high) * thread->fuse_corner_count,
					GFP_KERNEL);
	if (!fmax_corner || !quot_low || !quot_high) {
	if (!volt_adjust || !volt_adjust_fuse || !ro_scale ||
	    !fmax_corner || !quot_low || !quot_high) {
		cpr3_err(thread, "unable to allocate temp memory\n");
		rc = -ENOMEM;
		goto done;
	}

	rc = cpr3_hmss_parse_closed_loop_voltage_adjustments(thread, corner_sum,
		combo_offset, volt_adjust, volt_adjust_fuse, ro_scale);
	if (rc) {
		cpr3_err(thread, "could not load closed-loop voltage adjustments, rc=%d\n",
			rc);
		goto done;
	}

	if (!allow_interpolation) {
		/* Use fused target quotients for lower frequencies. */
		return cpr3_msm8996_hmss_set_no_interpolation_quotients(thread,
				volt_adjust, volt_adjust_fuse, ro_scale);
	}

	/* Determine highest corner mapped to each fuse corner */
	j = thread->fuse_corner_count - 1;
	for (i = thread->corner_count - 1; i >= 0; i--) {
@@ -788,8 +935,13 @@ static int cpr3_msm8996_hmss_calculate_target_quotients(
	 * Interpolation is not possible for corners mapped to the lowest fuse
	 * corner so use the fuse corner value directly.
	 */
	quot = fuse->target_quot[CPR3_MSM8996_HMSS_FUSE_CORNER_MINSVS];
	ro = fuse->ro_sel[CPR3_MSM8996_HMSS_FUSE_CORNER_MINSVS];
	i = CPR3_MSM8996_HMSS_FUSE_CORNER_MINSVS;
	quot_adjust = cpr3_quot_adjustment(ro_scale[i], volt_adjust_fuse[i]);
	quot = fuse->target_quot[i] + quot_adjust;
	ro = fuse->ro_sel[i];
	if (quot_adjust)
		cpr3_info(thread, "adjusted fuse corner %d RO%u target quot: %llu --> %u (%d uV)\n",
			i, ro, fuse->target_quot[i], quot, volt_adjust_fuse[i]);
	for (i = 0; i <= fmax_corner[CPR3_MSM8996_HMSS_FUSE_CORNER_MINSVS]; i++)
		thread->corner[i].target_quot[ro] = quot;

@@ -804,7 +956,8 @@ static int cpr3_msm8996_hmss_calculate_target_quotients(
				fuse->quot_offset[i]
					* MSM8996_HMSS_QUOT_OFFSET_SCALE);
			rc = cpr3_msm8996_hmss_set_no_interpolation_quotients(
				thread);
				thread, volt_adjust, volt_adjust_fuse,
				ro_scale);
			goto done;
		}
	}
@@ -814,7 +967,8 @@ static int cpr3_msm8996_hmss_calculate_target_quotients(
		cpr3_err(thread, "MinSVS RO=%llu is not the same as SVS RO=%llu; interpolation not possible\n",
			fuse->ro_sel[CPR3_MSM8996_HMSS_FUSE_CORNER_MINSVS],
			fuse->ro_sel[CPR3_MSM8996_HMSS_FUSE_CORNER_SVS]);
		rc = cpr3_msm8996_hmss_set_no_interpolation_quotients(thread);
		rc = cpr3_msm8996_hmss_set_no_interpolation_quotients(thread,
			volt_adjust, volt_adjust_fuse, ro_scale);
		goto done;
	}

@@ -830,10 +984,36 @@ static int cpr3_msm8996_hmss_calculate_target_quotients(
	if (quot_low[i] > quot_high[i]) {
		cpr3_err(thread, "invalid quot_lowsvs=%llu and quot_minsvs=%llu; interpolation not possible\n",
			quot_high[i], quot_low[i]);
		rc = cpr3_msm8996_hmss_set_no_interpolation_quotients(thread);
		rc = cpr3_msm8996_hmss_set_no_interpolation_quotients(thread,
			volt_adjust, volt_adjust_fuse, ro_scale);
		goto done;
	}

	/* Perform per-fuse-corner target quotient adjustment */
	for (i = 1; i < thread->fuse_corner_count; i++) {
		quot_adjust = cpr3_quot_adjustment(ro_scale[i],
						   volt_adjust_fuse[i]);
		if (quot_adjust) {
			prev_quot = quot_high[i];
			quot_high[i] += quot_adjust;
			cpr3_info(thread, "adjusted fuse corner %d RO%llu target quot: %llu --> %llu (%d uV)\n",
				i, fuse->ro_sel[i], prev_quot, quot_high[i],
				volt_adjust_fuse[i]);
		}

		quot_low[i] += cpr3_quot_adjustment(ro_scale[i],
						    volt_adjust_fuse[i - 1]);

		if (quot_low[i] > quot_high[i]) {
			cpr3_err(thread, "invalid quot_high[%d]=%llu and quot_low[%d]=%llu after adjustment; interpolation not possible\n",
				i, quot_high[i], i, quot_low[i]);
			rc = cpr3_msm8996_hmss_set_no_interpolation_quotients(
				thread, volt_adjust, volt_adjust_fuse,
				ro_scale);
			goto done;
		}
	}

	/* Interpolate voltages for the higher fuse corners. */
	for (i = 1; i < thread->fuse_corner_count; i++) {
		freq_low = thread->corner[fmax_corner[i - 1]].proc_freq;
@@ -846,7 +1026,26 @@ static int cpr3_msm8996_hmss_calculate_target_quotients(
				thread->corner[j].proc_freq);
	}

	/* Perform per-corner target quotient adjustment */
	for (i = 0; i < thread->corner_count; i++) {
		fuse_corner = thread->corner[i].cpr_fuse_corner;
		ro = fuse->ro_sel[fuse_corner];
		quot_adjust = cpr3_quot_adjustment(ro_scale[fuse_corner],
						   volt_adjust[i]);
		if (quot_adjust) {
			prev_quot = thread->corner[i].target_quot[ro];
			thread->corner[i].target_quot[ro] += quot_adjust;
			cpr3_info(thread, "adjusted corner %d RO%u target quot: %llu --> %u (%d uV)\n",
				i, ro, prev_quot,
				thread->corner[i].target_quot[ro],
				volt_adjust[i]);
		}
	}

done:
	kfree(volt_adjust);
	kfree(volt_adjust_fuse);
	kfree(ro_scale);
	kfree(fmax_corner);
	kfree(quot_low);
	kfree(quot_high);
@@ -888,6 +1087,8 @@ static void cpr3_hmss_print_settings(struct cpr3_thread *thread)
static int cpr3_hmss_init_thread(struct cpr3_thread *thread)
{
	struct cpr3_msm8996_hmss_fuses *fuse;
	int corner_sum = 0;
	int combo_offset = 0;
	int rc;

	rc = cpr3_msm8996_hmss_read_fuse_data(thread);
@@ -912,14 +1113,15 @@ static int cpr3_hmss_init_thread(struct cpr3_thread *thread)
		return rc;
	}

	rc = cpr3_hmss_parse_corner_data(thread);
	rc = cpr3_hmss_parse_corner_data(thread, &corner_sum, &combo_offset);
	if (rc) {
		cpr3_err(thread, "unable to read CPR corner data from device tree, rc=%d\n",
			rc);
		return rc;
	}

	rc = cpr3_msm8996_hmss_calculate_open_loop_voltages(thread);
	rc = cpr3_msm8996_hmss_calculate_open_loop_voltages(thread, corner_sum,
			combo_offset);
	if (rc) {
		cpr3_err(thread, "unable to calculate open-loop voltages, rc=%d\n",
			rc);
@@ -942,7 +1144,8 @@ static int cpr3_hmss_init_thread(struct cpr3_thread *thread)

	cpr3_open_loop_voltage_as_ceiling(thread);

	rc = cpr3_msm8996_hmss_calculate_target_quotients(thread);
	rc = cpr3_msm8996_hmss_calculate_target_quotients(thread, corner_sum,
			combo_offset);
	if (rc) {
		cpr3_err(thread, "unable to calculate target quotients, rc=%d\n",
			rc);
+121 −9

File changed.

Preview size limit exceeded, changes collapsed.

Loading