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

Commit dcf4a3a9 authored by Anirudh Ghayal's avatar Anirudh Ghayal
Browse files

regulator: cpr-regulator: Add virtual-corner voltage/quotient adjustment



Add support to adjust the target quotient and init-voltage per virtual
corner. The adjustment values are specified via DT properties.
This allows finer granularity for quotient/voltage adjustments.

Change-Id: I3deffb070a0156acf9ceaa138357ae208a86df59
Signed-off-by: default avatarAnirudh Ghayal <aghayal@codeaurora.org>
parent 53b0db65
Loading
Loading
Loading
Loading
+36 −0
Original line number Diff line number Diff line
@@ -383,6 +383,34 @@ Optional properties:
				voltages will be used in place of the per-fuse-corner floor voltages defined in the
				qcom,cpr-voltage-floor property.  If this property is not specified, then the
				per-fuse-corner floor voltages will always be used.
- qcom,cpr-virtual-corner-init-voltage-adjustment: Array of integer tuples of voltage adjustments in microvolts to be
				added to the initial voltage values of each virtual corner.  The elements
				in a tuple are ordered from lowest voltage corner to highest voltage corner.
				Each tuple must be of the length equal to the number of virtual corners as
				specified by the number of elements in the qcom,cpr-corner-map property. If the
				qcom,cpr-fuse-version-map property is specified, then
				qcom,cpr-virtual-corner-init-voltage-adjustment must contain the same number of
				tuples as qcom,cpr-fuse-version-map.  These tuples are then mapped one-to-one in the
				order specified.  E.g. if the second qcom,cpr-fuse-version-map tuple matches
				for a given device, then voltage adjustments defined in the second
				qcom,cpr-virtual-corner-init-voltage-adjustment tuple will be applied.  If the
				qcom,cpr-fuse-version-map property is not specified, then
				qcom,cpr-virtual-corner-init-voltage-adjustment must contain a single tuple which
				is then applied unconditionally.
- qcom,cpr-virtual-corner-quotient-adjustment: Array of integer tuples of quotient offsets to be added to
				the scaled target quotient of each virtual corner. The elements
				in a tuple are ordered from lowest voltage corner to highest voltage corner.
				Each tuple must be of the length equal to the number of virtual corners as
				specified by the number of elements in the qcom,cpr-corner-map property.
				If the qcom,cpr-fuse-version-map property is specified, then
				qcom,cpr-virtual-corner-quotient-adjustment must contain the same number of tuples as
				qcom,cpr-fuse-version-map.  These tuples are then mapped one-to-one in the
				order specified.  E.g. if the second qcom,cpr-fuse-version-map tuple matches
				for a given device, then quotient adjustments defined in the second
				qcom,cpr-virtual-corner-quotient-adjustment tuple will be applied.  If the
				qcom,cpr-fuse-version-map property is not specified, then
				qcom,cpr-virtual-corner-quotient-adjustment must contain a single tuple which is then
				applied unconditionally.
- qcom,cpr-init-voltage-as-ceiling: Boolean which indicates that the ceiling voltage used for a given virtual
				corner may be reduced to the per-fuse-corner initial voltage fuse value.
- qcom,cpr-scaled-init-voltage-as-ceiling: Boolean which indicates that the ceiling voltage used for a given
@@ -632,6 +660,14 @@ Example:
				<0 0 (-100000)>,
				<0 0 (-100000)>,
				<0 0 (-45000)>;
		qcom,cpr-virtual-corner-init-voltage-adjustment =
			<0 0 0 (-10000) 0 0 0 0 0 0 0 0>,
			<0 0 0 0 0 0 0 0 0 0 0 (-20000)>,
			<0 0 0 0 0 0 0 0 0 0 0 (-30000)>;
		qcom,cpr-virtual-corner-quotient-adjustment =
			<0 0 0 100 0 0 0 0 0 0 0 0>,
			<0 0 0 0 0 0 0 0 0 0 0 (-300)>,
			<0 0 0 (-60) 0 0 0 0 0 0 0 0>;

		qcom,fuse-remap-base-row = <1000>;
		qcom,fuse-remap-source =
+132 −1
Original line number Diff line number Diff line
@@ -1935,6 +1935,119 @@ static int cpr_reduce_ceiling_voltage(struct cpr_regulator *cpr_vreg,
	return 0;
}

/*
 * Adjust the per-virtual-corner open loop voltage with an offset specfied by a
 * device-tree property. This must be called after open-loop voltage scaling.
 */
static int cpr_virtual_corner_voltage_adjust(struct cpr_regulator *cpr_vreg,
						struct device *dev)
{
	char *prop_name = "qcom,cpr-virtual-corner-init-voltage-adjustment";
	int i, rc, tuple_count, tuple_match, index, len;
	u32 voltage_adjust;

	if (!of_find_property(dev->of_node, prop_name, &len)) {
		cpr_debug(cpr_vreg, "%s not specified\n", prop_name);
		return 0;
	}

	if (cpr_vreg->cpr_fuse_map_count) {
		if (cpr_vreg->cpr_fuse_map_match == FUSE_MAP_NO_MATCH) {
			/* No matching index to use for voltage adjustment. */
			return 0;
		}
		tuple_count = cpr_vreg->cpr_fuse_map_count;
		tuple_match = cpr_vreg->cpr_fuse_map_match;
	} else {
		tuple_count = 1;
		tuple_match = 0;
	}

	if (len != cpr_vreg->num_corners * tuple_count * sizeof(u32)) {
		cpr_err(cpr_vreg, "%s length=%d is invalid\n", prop_name,
			len);
		return -EINVAL;
	}

	for (i = CPR_CORNER_MIN; i <= cpr_vreg->num_corners; i++) {
		index = tuple_match * cpr_vreg->num_corners
				+ i - CPR_CORNER_MIN;
		rc = of_property_read_u32_index(dev->of_node, prop_name,
						index, &voltage_adjust);
		if (rc) {
			cpr_err(cpr_vreg, "could not read %s index %u, rc=%d\n",
				prop_name, index, rc);
			return rc;
		}

		if (voltage_adjust) {
			cpr_vreg->open_loop_volt[i] += (int)voltage_adjust;
			cpr_info(cpr_vreg, "corner=%d adjusted open-loop voltage=%d\n",
				i, cpr_vreg->open_loop_volt[i]);
		}
	}

	return 0;
}

/*
 * Adjust the per-virtual-corner quot with an offset specfied by a
 * device-tree property. This must be called after the quot-scaling adjustments
 * are completed.
 */
static int cpr_virtual_corner_quot_adjust(struct cpr_regulator *cpr_vreg,
						struct device *dev)
{
	char *prop_name = "qcom,cpr-virtual-corner-quotient-adjustment";
	int i, rc, tuple_count, tuple_match, index, len;
	u32 quot_adjust;

	if (!of_find_property(dev->of_node, prop_name, &len)) {
		cpr_debug(cpr_vreg, "%s not specified\n", prop_name);
		return 0;
	}

	if (cpr_vreg->cpr_fuse_map_count) {
		if (cpr_vreg->cpr_fuse_map_match == FUSE_MAP_NO_MATCH) {
			/* No matching index to use for quotient adjustment. */
			return 0;
		}
		tuple_count = cpr_vreg->cpr_fuse_map_count;
		tuple_match = cpr_vreg->cpr_fuse_map_match;
	} else {
		tuple_count = 1;
		tuple_match = 0;
	}

	if (len != cpr_vreg->num_corners * tuple_count * sizeof(u32)) {
		cpr_err(cpr_vreg, "%s length=%d is invalid\n", prop_name,
			len);
		return -EINVAL;
	}

	for (i = CPR_CORNER_MIN; i <= cpr_vreg->num_corners; i++) {
		index = tuple_match * cpr_vreg->num_corners
				+ i - CPR_CORNER_MIN;
		rc = of_property_read_u32_index(dev->of_node, prop_name,
						index, &quot_adjust);
		if (rc) {
			cpr_err(cpr_vreg, "could not read %s index %u, rc=%d\n",
				prop_name, index, rc);
			return rc;
		}

		if (quot_adjust) {
			cpr_vreg->quot_adjust[i] -= (int)quot_adjust;
			cpr_info(cpr_vreg, "corner=%d adjusted quotient=%d\n",
					i,
			cpr_vreg->cpr_fuse_target_quot[cpr_vreg->corner_map[i]]
						- cpr_vreg->quot_adjust[i]);
		}
	}

	return 0;
}

/*
 * cpr_get_corner_quot_adjustment() -- get the quot_adjust for each corner.
 *
@@ -2246,21 +2359,39 @@ static int cpr_get_corner_quot_adjustment(struct cpr_regulator *cpr_vreg,
			}
		}
	}

	rc = cpr_virtual_corner_quot_adjust(cpr_vreg, dev);
	if (rc) {
		cpr_err(cpr_vreg, "count not adjust virtual-corner quot rc=%d\n",
			rc);
		goto free_arrays;
	}

	for (i = CPR_CORNER_MIN; i <= cpr_vreg->num_corners; i++)
		cpr_info(cpr_vreg, "adjusted quotient[%d] = %d\n", i,
			cpr_vreg->cpr_fuse_target_quot[cpr_vreg->corner_map[i]]
			- cpr_vreg->quot_adjust[i]);

	maps_valid = true;

free_arrays:
	if (!rc) {

		rc = cpr_get_open_loop_voltage(cpr_vreg, dev, corner_max,
						freq_map, maps_valid);
		if (rc)
		if (rc) {
			cpr_err(cpr_vreg, "could not fill open loop voltage array, rc=%d\n",
				rc);
			goto free_arrays_1;
		}

		rc = cpr_virtual_corner_voltage_adjust(cpr_vreg, dev);
		if (rc)
			cpr_err(cpr_vreg, "count not adjust virtual-corner voltage rc=%d\n",
				rc);
	}

free_arrays_1:
	kfree(max_factor);
	kfree(scaling);
	kfree(freq_map);