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

Commit 656613cd authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "regulator: cpr3-regulator: change adjustment messages to debug log level"

parents 8e011d36 2e200780
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -119,6 +119,32 @@ MMSS specific properties:
		    or the qcom,cpr-speed-bins property as opposed to the value
		    of the qcom,cpr-fuse-corners property.

- qcom,cpr-fused-closed-loop-voltage-adjustment-map
	Usage:      optional
	Value type: <prop-encoded-array>
	Definition: A list of integer tuples which each define the CPR fused
		    corner closed-loop offset adjustment fuse to utilize for
		    each voltage corner in order from lowest to highest.

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

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

		    Each tuple element must be either 0 or in the range 1 to
		    qcom,cpr-fuse-corners.  A value of 0 signifies that no fuse
		    based adjustment should be applied to the fuse corner.
		    Values 1 to qcom,cpr-fuse-corners denote the specific fuse
		    corner that should be used by a given voltage corner.

Note that the qcom,cpr-closed-loop-voltage-fuse-adjustment property is not
meaningful for MMSS CPR3 regulator nodes since target quotients are not defined
in fuses.
@@ -205,6 +231,9 @@ gfx_cpr: cpr3-ctrl@838000 {
			qcom,cpr-closed-loop-voltage-adjustment =
				<45000 0 0 0>;

			qcom,cpr-fused-closed-loop-voltage-adjustment-map =
				<2 2 0 4>;

			qcom,allow-voltage-interpolation;
			qcom,cpr-scaled-open-loop-voltage-as-ceiling;

+8 −8
Original line number Diff line number Diff line
@@ -656,7 +656,7 @@ static int cpr3_msm8996_hmss_calculate_open_loop_voltages(

	for (i = 1; i < vreg->fuse_corner_count; i++) {
		if (fuse_volt[i] < fuse_volt[i - 1]) {
			cpr3_info(vreg, "fuse corner %d voltage=%d uV < fuse corner %d voltage=%d uV; overriding: fuse corner %d voltage=%d\n",
			cpr3_debug(vreg, "fuse corner %d voltage=%d uV < fuse corner %d voltage=%d uV; overriding: fuse corner %d voltage=%d\n",
				i, fuse_volt[i], i - 1, fuse_volt[i - 1],
				i, fuse_volt[i - 1]);
			fuse_volt[i] = fuse_volt[i - 1];
@@ -923,7 +923,7 @@ static int cpr3_msm8996_hmss_set_no_interpolation_quotients(
		ro = fuse->ro_sel[fuse_corner];
		vreg->corner[i].target_quot[ro] = quot + quot_adjust;
		if (quot_adjust)
			cpr3_info(vreg, "adjusted corner %d RO%u target quot: %u --> %u (%d uV)\n",
			cpr3_debug(vreg, "adjusted corner %d RO%u target quot: %u --> %u (%d uV)\n",
				i, ro, quot, vreg->corner[i].target_quot[ro],
				volt_adjust_fuse[fuse_corner] + volt_adjust[i]);
	}
@@ -1035,7 +1035,7 @@ static int cpr3_msm8996_hmss_calculate_target_quotients(
	quot_high[i] = quot;
	ro = fuse->ro_sel[i];
	if (quot_adjust)
		cpr3_info(vreg, "adjusted fuse corner %d RO%u target quot: %llu --> %u (%d uV)\n",
		cpr3_debug(vreg, "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++)
		vreg->corner[i].target_quot[ro] = quot;
@@ -1074,7 +1074,7 @@ static int cpr3_msm8996_hmss_calculate_target_quotients(
					- fuse->quot_offset[i]
					  * MSM8996_HMSS_QUOT_OFFSET_SCALE;
		if (quot_high[i] < quot_low[i]) {
			cpr3_info(vreg, "quot_high[%d]=%llu < quot_low[%d]=%llu; overriding: quot_high[%d]=%llu\n",
			cpr3_debug(vreg, "quot_high[%d]=%llu < quot_low[%d]=%llu; overriding: quot_high[%d]=%llu\n",
				i, quot_high[i], i, quot_low[i],
				i, quot_low[i]);
			quot_high[i] = quot_low[i];
@@ -1088,7 +1088,7 @@ static int cpr3_msm8996_hmss_calculate_target_quotients(
		if (quot_adjust) {
			prev_quot = quot_high[i];
			quot_high[i] += quot_adjust;
			cpr3_info(vreg, "adjusted fuse corner %d RO%llu target quot: %llu --> %llu (%d uV)\n",
			cpr3_debug(vreg, "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]);
		}
@@ -1100,7 +1100,7 @@ static int cpr3_msm8996_hmss_calculate_target_quotients(
						    volt_adjust_fuse[i - 1]);

		if (quot_high[i] < quot_low[i]) {
			cpr3_info(vreg, "quot_high[%d]=%llu < quot_low[%d]=%llu after adjustment; overriding: quot_high[%d]=%llu\n",
			cpr3_debug(vreg, "quot_high[%d]=%llu < quot_low[%d]=%llu after adjustment; overriding: quot_high[%d]=%llu\n",
				i, quot_high[i], i, quot_low[i],
				i, quot_low[i]);
			quot_high[i] = quot_low[i];
@@ -1128,7 +1128,7 @@ static int cpr3_msm8996_hmss_calculate_target_quotients(
		if (quot_adjust) {
			prev_quot = vreg->corner[i].target_quot[ro];
			vreg->corner[i].target_quot[ro] += quot_adjust;
			cpr3_info(vreg, "adjusted corner %d RO%u target quot: %llu --> %u (%d uV)\n",
			cpr3_debug(vreg, "adjusted corner %d RO%u target quot: %llu --> %u (%d uV)\n",
				i, ro, prev_quot,
				vreg->corner[i].target_quot[ro],
				volt_adjust[i]);
@@ -1141,7 +1141,7 @@ static int cpr3_msm8996_hmss_calculate_target_quotients(
		if (fuse->ro_sel[vreg->corner[i - 1].cpr_fuse_corner] == ro
		    && vreg->corner[i].target_quot[ro]
				< vreg->corner[i - 1].target_quot[ro]) {
			cpr3_info(vreg, "adjusted corner %d RO%u target quot=%u < adjusted corner %d RO%u target quot=%u; overriding: corner %d RO%u target quot=%u\n",
			cpr3_debug(vreg, "adjusted corner %d RO%u target quot=%u < adjusted corner %d RO%u target quot=%u; overriding: corner %d RO%u target quot=%u\n",
				i, ro, vreg->corner[i].target_quot[ro],
				i - 1, ro, vreg->corner[i - 1].target_quot[ro],
				i, ro, vreg->corner[i - 1].target_quot[ro]);
+234 −54
Original line number Diff line number Diff line
@@ -41,6 +41,9 @@
 * struct cpr3_msm8996_mmss_fuses - MMSS specific fuse data for MSM8996
 * @init_voltage:	Initial (i.e. open-loop) voltage fuse parameter value
 *			for each fuse corner (raw, not converted to a voltage)
 * @offset_voltage:	The closed-loop voltage margin adjustment fuse parameter
 *			value for each fuse corner (raw, not converted to a
 *			voltage)
 * @cpr_fusing_rev:	CPR fusing revision fuse parameter value
 * @limitation:		CPR limitation select fuse parameter value
 * @aging_init_quot_diff:	Initial quotient difference between CPR aging
@@ -50,6 +53,7 @@
 */
struct cpr3_msm8996_mmss_fuses {
	u64	init_voltage[MSM8996_MMSS_FUSE_CORNERS];
	u64	offset_voltage[MSM8996_MMSS_FUSE_CORNERS];
	u64	cpr_fusing_rev;
	u64	limitation;
	u64	aging_init_quot_diff;
@@ -119,6 +123,15 @@ msm8996_mmss_aging_init_quot_diff_param[] = {
	{},
};

/* Offset voltages are defined for SVS and Turbo fuse corners only */
static const struct cpr3_fuse_param
msm8996_mmss_offset_voltage_param[MSM8996_MMSS_FUSE_CORNERS][2] = {
	{{} },
	{{66, 42, 44}, {} },
	{{} },
	{{64, 58, 61}, {} },
};

/*
 * Some initial msm8996 parts cannot be used in a meaningful way by software.
 * Other parts can only be used when operating with CPR disabled (i.e. at the
@@ -142,6 +155,7 @@ static const int msm8996_mmss_fuse_ref_volt[MSM8996_MMSS_FUSE_CORNERS] = {
};

#define MSM8996_MMSS_FUSE_STEP_VOLT		10000
#define MSM8996_MMSS_OFFSET_FUSE_STEP_VOLT	10000
#define MSM8996_MMSS_VOLTAGE_FUSE_SIZE		5
#define MSM8996_MMSS_AGING_INIT_QUOT_DIFF_SCALE	2
#define MSM8996_MMSS_AGING_INIT_QUOT_DIFF_SIZE	6
@@ -212,6 +226,15 @@ static int cpr3_msm8996_mmss_read_fuse_data(struct cpr3_regulator *vreg)
				i, rc);
			return rc;
		}

		rc = cpr3_read_fuse_param(base,
			msm8996_mmss_offset_voltage_param[i],
			&fuse->offset_voltage[i]);
		if (rc) {
			cpr3_err(vreg, "Unable to read fuse-corner %d offset voltage fuse, rc=%d\n",
				i, rc);
			return rc;
		}
	}

	vreg->fuse_combo = fuse->cpr_fusing_rev;
@@ -267,24 +290,207 @@ done:
	return rc;
}

/**
 * cpr3_msm8996_mmss_apply_closed_loop_offset_voltages() - modify the
 *		closed-loop voltage adjustments by the amounts that are needed
 *		for this fuse combo
 * @vreg:		Pointer to the CPR3 regulator
 * @volt_adjust:	Array of closed-loop voltage adjustment values of length
 *			vreg->corner_count which is further adjusted based upon
 *			offset voltage fuse values.
 *
 * Return: 0 on success, errno on failure
 */
static int cpr3_msm8996_mmss_apply_closed_loop_offset_voltages(
			struct cpr3_regulator *vreg, int *volt_adjust)
{
	struct cpr3_msm8996_mmss_fuses *fuse = vreg->platform_fuses;
	u32 *corner_map;
	int *volt_offset;
	int rc = 0, i, fuse_len;

	if (!of_find_property(vreg->of_node,
		"qcom,cpr-fused-closed-loop-voltage-adjustment-map", NULL)) {
		/* No closed-loop offset required. */
		return 0;
	}

	corner_map = kcalloc(vreg->corner_count, sizeof(*corner_map),
				GFP_KERNEL);
	volt_offset = kcalloc(vreg->fuse_corner_count, sizeof(*volt_offset),
				GFP_KERNEL);
	if (!corner_map || !volt_offset) {
		rc = -ENOMEM;
		goto done;
	}

	rc = cpr3_parse_corner_array_property(vreg,
		"qcom,cpr-fused-closed-loop-voltage-adjustment-map",
		1, corner_map);
	if (rc)
		goto done;

	for (i = 0; i < vreg->fuse_corner_count; i++) {
		fuse_len = msm8996_mmss_offset_voltage_param[i][0].bit_end + 1
			   - msm8996_mmss_offset_voltage_param[i][0].bit_start;
		volt_offset[i] = cpr3_convert_open_loop_voltage_fuse(
			0, MSM8996_MMSS_OFFSET_FUSE_STEP_VOLT,
			fuse->offset_voltage[i], fuse_len);
		if (volt_offset[i])
			cpr3_info(vreg, "fuse_corner[%d] offset=%7d uV\n",
				i, volt_offset[i]);
	}

	for (i = 0; i < vreg->corner_count; i++) {
		if (corner_map[i] == 0) {
			continue;
		} else if (corner_map[i] > vreg->fuse_corner_count) {
			cpr3_err(vreg, "corner %d mapped to invalid fuse corner: %u\n",
				i, corner_map[i]);
			rc = -EINVAL;
			goto done;
		}

		volt_adjust[i] += volt_offset[corner_map[i] - 1];
	}

done:
	kfree(corner_map);
	kfree(volt_offset);

	return rc;
}

/**
 * cpr3_mmss_enforce_inc_quotient_monotonicity() - Ensure that target quotients
 *		increase monotonically from lower to higher corners
 * @vreg:		Pointer to the CPR3 regulator
 *
 * Return: 0 on success, errno on failure
 */
static void cpr3_mmss_enforce_inc_quotient_monotonicity(
		struct cpr3_regulator *vreg)
{
	int i, j;

	for (i = 1; i < vreg->corner_count; i++) {
		for (j = 0; j < CPR3_RO_COUNT; j++) {
			if (vreg->corner[i].target_quot[j]
			    && vreg->corner[i].target_quot[j]
					< vreg->corner[i - 1].target_quot[j]) {
				cpr3_debug(vreg, "corner %d RO%u target quot=%u < corner %d RO%u target quot=%u; overriding: corner %d RO%u target quot=%u\n",
					i, j,
					vreg->corner[i].target_quot[j],
					i - 1, j,
					vreg->corner[i - 1].target_quot[j],
					i, j,
					vreg->corner[i - 1].target_quot[j]);
				vreg->corner[i].target_quot[j]
					= vreg->corner[i - 1].target_quot[j];
			}
		}
	}
}

/**
 * cpr3_mmss_enforce_dec_quotient_monotonicity() - Ensure that target quotients
 *		decrease monotonically from higher to lower corners
 * @vreg:		Pointer to the CPR3 regulator
 *
 * Return: 0 on success, errno on failure
 */
static void cpr3_mmss_enforce_dec_quotient_monotonicity(
		struct cpr3_regulator *vreg)
{
	int i, j;

	for (i = vreg->corner_count - 2; i >= 0; i--) {
		for (j = 0; j < CPR3_RO_COUNT; j++) {
			if (vreg->corner[i].target_quot[j]
			    && vreg->corner[i].target_quot[j]
					> vreg->corner[i + 1].target_quot[j]) {
				cpr3_debug(vreg, "corner %d RO%u target quot=%u > corner %d RO%u target quot=%u; overriding: corner %d RO%u target quot=%u\n",
					i, j,
					vreg->corner[i].target_quot[j],
					i + 1, j,
					vreg->corner[i + 1].target_quot[j],
					i, j,
					vreg->corner[i + 1].target_quot[j]);
				vreg->corner[i].target_quot[j]
					= vreg->corner[i + 1].target_quot[j];
			}
		}
	}
}

/**
 * _cpr3_mmss_adjust_target_quotients() - adjust the target quotients for each
 *		corner of the regulator according to input adjustment and
 *		scaling arrays
 * @vreg:		Pointer to the CPR3 regulator
 * @volt_adjust:	Pointer to an array of closed-loop voltage adjustments
 *			with units of microvolts.  The array must have
 *			vreg->corner_count number of elements.
 * @ro_scale:		Pointer to a flattened 2D array of RO scaling factors.
 *			The array must have an inner dimension of CPR3_RO_COUNT
 *			and an outer dimension of vreg->corner_count
 * @label:		Null terminated string providing a label for the type
 *			of adjustment.
 *
 * Return: true if any corners received a positive voltage adjustment (> 0),
 *	   else false
 */
static bool _cpr3_mmss_adjust_target_quotients(struct cpr3_regulator *vreg,
		const int *volt_adjust, const int *ro_scale, const char *label)
{
	int i, j, quot_adjust;
	bool is_increasing = false;
	u32 prev_quot;

	for (i = 0; i < vreg->corner_count; i++) {
		for (j = 0; j < CPR3_RO_COUNT; j++) {
			if (vreg->corner[i].target_quot[j]) {
				quot_adjust = cpr3_quot_adjustment(
					ro_scale[i * CPR3_RO_COUNT + j],
					volt_adjust[i]);
				if (quot_adjust) {
					prev_quot = vreg->corner[i].
							target_quot[j];
					vreg->corner[i].target_quot[j]
						+= quot_adjust;
					cpr3_debug(vreg, "adjusted corner %d RO%d target quot %s: %u --> %u (%d uV)\n",
						i, j, label, prev_quot,
						vreg->corner[i].target_quot[j],
						volt_adjust[i]);
				}
			}
		}
		if (volt_adjust[i] > 0)
			is_increasing = true;
	}

	return is_increasing;
}

/**
 * cpr3_mmss_adjust_target_quotients() - adjust the target quotients for each
 *		corner according to device tree values
 *		corner according to device tree values and fuse values
 * @vreg:		Pointer to the CPR3 regulator
 *
 * Return: 0 on success, errno on failure
 */
static int cpr3_mmss_adjust_target_quotients(struct cpr3_regulator *vreg)
{
	int i, j, rc, quot_adjust;
	int i, rc;
	int *volt_adjust, *ro_scale;
	bool explicit_adjustment;
	u32 prev_quot;
	bool explicit_adjustment, fused_adjustment, is_increasing;

	explicit_adjustment = of_find_property(vreg->of_node,
		"qcom,cpr-closed-loop-voltage-adjustment", NULL);
	fused_adjustment = of_find_property(vreg->of_node,
		"qcom,cpr-fused-closed-loop-voltage-adjustment-map", NULL);

	if (!explicit_adjustment && !vreg->aging_allowed) {
	if (!explicit_adjustment && !fused_adjustment && !vreg->aging_allowed) {
		/* No adjustment required. */
		return 0;
	} else if (!of_find_property(vreg->of_node,
@@ -324,55 +530,29 @@ static int cpr3_mmss_adjust_target_quotients(struct cpr3_regulator *vreg)
			goto done;
		}

		/*
		 * Adjust the target quotients for each corner according to
		 * device tree adjustment values.
		 */
		for (i = 0; i < vreg->corner_count; i++) {
			for (j = 0; j < CPR3_RO_COUNT; j++) {
				if (vreg->corner[i].target_quot[j]) {
					quot_adjust = cpr3_quot_adjustment(
						ro_scale[i * CPR3_RO_COUNT + j],
						volt_adjust[i]);
					if (quot_adjust) {
						prev_quot = vreg->corner[i].
								target_quot[j];
						vreg->corner[i].target_quot[j]
						     += quot_adjust;
						cpr3_info(vreg, "adjusted corner %d RO%d target quot: %u --> %u (%d uV)\n",
						     i, j, prev_quot,
						     vreg->corner[i].
							     target_quot[j],
						     volt_adjust[i]);
					}
				}
			}
		_cpr3_mmss_adjust_target_quotients(vreg, volt_adjust, ro_scale,
			"from DT");
		cpr3_mmss_enforce_inc_quotient_monotonicity(vreg);
	}

		/*
		 * Ensure that target quotients increase monotonically from
		 * lower to higher corners after being adjusted based upon
		 * device tree adjustment values.
		 */
		for (i = 1; i < vreg->corner_count; i++) {
			for (j = 0; j < CPR3_RO_COUNT; j++) {
				if (vreg->corner[i].target_quot[j]
				    && vreg->corner[i].target_quot[j]
					 < vreg->corner[i - 1].target_quot[j]) {
					cpr3_info(vreg, "adjusted corner %d RO%u target quot=%u < adjusted corner %d RO%u target quot=%u; overriding: corner %d RO%u target quot=%u\n",
						i, j,
						vreg->corner[i].target_quot[j],
						i - 1, j,
						vreg->corner[i - 1].
							target_quot[j],
						i, j,
						vreg->corner[i - 1].
							target_quot[j]);
					vreg->corner[i].target_quot[j]
					   = vreg->corner[i - 1].target_quot[j];
				}
			}
	if (fused_adjustment) {
		memset(volt_adjust, 0,
			sizeof(*volt_adjust) * vreg->corner_count);

		rc = cpr3_msm8996_mmss_apply_closed_loop_offset_voltages(vreg,
			volt_adjust);
		if (rc) {
			cpr3_err(vreg, "could not apply fused closed-loop voltage reductions, rc=%d\n",
				rc);
			goto done;
		}

		is_increasing = _cpr3_mmss_adjust_target_quotients(vreg,
					volt_adjust, ro_scale, "from fuse");
		if (is_increasing)
			cpr3_mmss_enforce_inc_quotient_monotonicity(vreg);
		else
			cpr3_mmss_enforce_dec_quotient_monotonicity(vreg);
	}

done:
@@ -440,7 +620,7 @@ static int cpr3_msm8996_mmss_calculate_open_loop_voltages(

	for (i = 1; i < vreg->fuse_corner_count; i++) {
		if (fuse_volt[i] < fuse_volt[i - 1]) {
			cpr3_info(vreg, "fuse corner %d voltage=%d uV < fuse corner %d voltage=%d uV; overriding: fuse corner %d voltage=%d\n",
			cpr3_debug(vreg, "fuse corner %d voltage=%d uV < fuse corner %d voltage=%d uV; overriding: fuse corner %d voltage=%d\n",
				i, fuse_volt[i], i - 1, fuse_volt[i - 1],
				i, fuse_volt[i - 1]);
			fuse_volt[i] = fuse_volt[i - 1];
+3 −3
Original line number Diff line number Diff line
@@ -1166,7 +1166,7 @@ int cpr3_adjust_fused_open_loop_voltages(struct cpr3_regulator *vreg,
		if (volt_adjust[i]) {
			prev_volt = fuse_volt[i];
			fuse_volt[i] += volt_adjust[i];
			cpr3_info(vreg, "adjusted fuse corner %d open-loop voltage: %d --> %d uV\n",
			cpr3_debug(vreg, "adjusted fuse corner %d open-loop voltage: %d --> %d uV\n",
				i, prev_volt, fuse_volt[i]);
		}
	}
@@ -1214,7 +1214,7 @@ int cpr3_adjust_open_loop_voltages(struct cpr3_regulator *vreg)
		if (volt_adjust[i]) {
			prev_volt = vreg->corner[i].open_loop_volt;
			vreg->corner[i].open_loop_volt += volt_adjust[i];
			cpr3_info(vreg, "adjusted corner %d open-loop voltage: %d --> %d uV\n",
			cpr3_debug(vreg, "adjusted corner %d open-loop voltage: %d --> %d uV\n",
				i, prev_volt, vreg->corner[i].open_loop_volt);
		}
	}
@@ -1237,7 +1237,7 @@ int cpr3_adjust_open_loop_voltages(struct cpr3_regulator *vreg)
	for (i = 1; i < vreg->corner_count; i++) {
		min_volt = vreg->corner[i - 1].open_loop_volt + volt_diff[i];
		if (vreg->corner[i].open_loop_volt < min_volt) {
			cpr3_info(vreg, "adjusted corner %d open-loop voltage=%d uV < corner %d voltage=%d uV + min diff=%d uV; overriding: corner %d voltage=%d\n",
			cpr3_debug(vreg, "adjusted corner %d open-loop voltage=%d uV < corner %d voltage=%d uV + min diff=%d uV; overriding: corner %d voltage=%d\n",
				i, vreg->corner[i].open_loop_volt,
				i - 1, vreg->corner[i - 1].open_loop_volt,
				volt_diff[i], i, min_volt);