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

Commit 31a41c69 authored by David Collins's avatar David Collins
Browse files

regulator: cpr-regulator: add support for CPR ceiling voltage reduction



Add support for a pair of device tree properties which specify
if the CPR ceiling voltage may be reduced to either the per-fuse-
corner initial voltage fuse value or the per-virtual-corner
interpolated initial voltage value (i.e. the open-loop voltage).

These properties can be used to save power on targets where the
closed-loop settled CPR voltage never needs to exceed the
open-loop initial voltage.

Change-Id: I359b6d8e0c98f4b7f00f7bd90efc72c2aa3865a7
Signed-off-by: default avatarDavid Collins <collinsd@codeaurora.org>
parent d2a8c71b
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -334,6 +334,14 @@ 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-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
				virtual corner may be reduced to the interpolated, per-virtual-corner initial
				voltage value.  Note that if both qcom,cpr-init-voltage-as-ceiling and
				qcom,cpr-scaled-init-voltage-as-ceiling are specified, then
				qcom,cpr-scaled-init-voltage-as-ceiling will take precedence since the interpolated
				voltages are necessarily less than or equal to the fused initial voltage values.
- qcom,cpr-voltage-scaling-factor-max: Array of values which define the maximum allowed scaling factor to apply
				when calculating per-corner initial voltage values for each fuse corner.  The
				array must be of length equal to the value of the qcom,cpr-fuse-corners property.
@@ -511,4 +519,5 @@ Example:
				<1 1 1050000 1050000 1050000 1050000 1060000
				     1070000 1080000 1090000 1100000 1100000
				     1100000 1100000>;
		qcom,cpr-scaled-init-voltage-as-ceiling;
	};
+42 −0
Original line number Diff line number Diff line
@@ -1784,6 +1784,43 @@ static int cpr_populate_opp_table(struct cpr_regulator *cpr_vreg,
	return 0;
}

/*
 * Conditionally reduce the per-virtual-corner ceiling voltages if certain
 * device tree flags are present.  This must be called only after the ceiling
 * array has been initialized and the open_loop_volt array values have been
 * initialized and limited to the existing floor to ceiling voltage range.
 */
static int cpr_reduce_ceiling_voltage(struct cpr_regulator *cpr_vreg,
				struct device *dev)
{
	bool reduce_to_fuse_open_loop, reduce_to_interpolated_open_loop;
	int i;

	reduce_to_fuse_open_loop = of_property_read_bool(dev->of_node,
				"qcom,cpr-init-voltage-as-ceiling");
	reduce_to_interpolated_open_loop = of_property_read_bool(dev->of_node,
				"qcom,cpr-scaled-init-voltage-as-ceiling");

	if (!reduce_to_fuse_open_loop && !reduce_to_interpolated_open_loop)
		return 0;

	for (i = CPR_CORNER_MIN; i <= cpr_vreg->num_corners; i++) {
		if (reduce_to_interpolated_open_loop &&
		    cpr_vreg->open_loop_volt[i] < cpr_vreg->ceiling_volt[i])
			cpr_vreg->ceiling_volt[i] = cpr_vreg->open_loop_volt[i];
		else if (reduce_to_fuse_open_loop &&
				cpr_vreg->pvs_corner_v[cpr_vreg->corner_map[i]]
				< cpr_vreg->ceiling_volt[i])
			cpr_vreg->ceiling_volt[i]
				= max((u32)cpr_vreg->floor_volt[i],
			       cpr_vreg->pvs_corner_v[cpr_vreg->corner_map[i]]);
		cpr_debug(cpr_vreg, "lowered ceiling[%d] = %d uV\n",
			i, cpr_vreg->ceiling_volt[i]);
	}

	return 0;
}

/*
 * cpr_get_corner_quot_adjustment() -- get the quot_adjust for each corner.
 *
@@ -2702,6 +2739,11 @@ static int cpr_init_cpr(struct platform_device *pdev,
	if (rc)
		return rc;

	/* Reduce the ceiling voltage if allowed. */
	rc = cpr_reduce_ceiling_voltage(cpr_vreg, &pdev->dev);
	if (rc)
		return rc;

	/* Init all voltage set points of APC regulator for CPR */
	rc = cpr_init_cpr_voltages(cpr_vreg, &pdev->dev);
	if (rc)