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

Commit 93c0f03e authored by Tirupathi Reddy's avatar Tirupathi Reddy
Browse files

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: default avatarTirupathi Reddy <tirupath@codeaurora.org>
parent a8371783
Loading
Loading
Loading
Loading
+28 −0
Original line number Diff line number Diff line
@@ -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;
+150 −1
Original line number Diff line number Diff line
@@ -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(