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

Commit 105054ca authored by Kyle Yan's avatar Kyle Yan Committed by Gerrit - the friendly Code Review server
Browse files

Merge "regulator: cprh-kbss-regulator: add support for SDM845 CPR controllers" into msm-4.9

parents 81de2c8e 54f78b79
Loading
Loading
Loading
Loading
+21 −5
Original line number Diff line number Diff line
@@ -36,16 +36,16 @@ Platform independent properties:
	Usage:      required
	Value type: <prop-encoded-array>
	Definition: Addresses and sizes for the memory of the CPR3 controller,
		    the first fuse row, and optionally a register used to check
		    if aging measurements are possible.
		    the first fuse row, and optionally the SAW module and/or a
		    register used to check if aging measurements are possible.

- reg-names
	Usage:      required
	Value type: <stringlist>
	Definition: Address names. Must include "cpr_ctrl" and "fuse_base".
		    "aging_allowed" may also be specified.  The strings must be
		    specified in the same order as the corresponding addresses
		    are specified in the reg property.
		    "aging_allowed" and "saw" may also be specified.  The
		    strings must be specified in the same order as the
		    corresponding addresses are specified in the reg property.

- qcom,cpr-ctrl-name
	Usage:      required
@@ -216,6 +216,22 @@ Platform independent properties:
		    as the corresponding addresses are specified in
		    the qcom,cpr-panic-reg-addr-list property.

- qcom,saw-avs-ctrl
	Usage:      required if "saw" registers are specified by reg and
		    reg-names properties
	Value type: <u32>
	Definition: SAW AVS_CTL register value to program at initialization time
		    in order to allow hardware closed-loop CPR voltage change
		    requests to reach the PMIC regulator.

- qcom,saw-avs-limit
	Usage:      required if "saw" registers are specified by reg and
		    reg-names properties
	Value type: <u32>
	Definition: SAW AVS_LIMIT register value to program at initialization
		    time in order to allow hardware closed-loop CPR voltage
		    change requests to reach the PMIC regulator.

=================================================
Second Level Nodes - CPR Threads for a Controller
=================================================
+11 −8
Original line number Diff line number Diff line
Qualcomm Technologies, Inc. CPRh Regulator - KBSS Specific Bindings

KBSS CPRh controllers each support one CPR thread that monitors the voltage
of a single Kryo-B CPU subystem (KBSS) cluster that is powered by a single
KBSS CPRh controllers each support one or more CPR threads that monitor the
voltage of Kryo-B CPU subystem (KBSS) clusters that are powered by a single
regulator supply. The DCVSh block interacts with the CPRh controller for full
hardware DCVS support.

@@ -15,9 +15,9 @@ Required Node Structure
=======================

CPRh regulators must be described in three levels of devices nodes.  The first
level describes the CPRh controller.  The second level describes one hardware
thread managed by the controller.  The third level describes one regulator
handled by the CPR thread.
level describes the CPRh controller.  The second level describes one or more
hardware threads managed by the controller.  The third level describes one
regulator handled by each CPR thread.

All platform independent cpr3-regulator binding guidelines defined in
cpr3-regulator.txt also apply to cprh-kbss-regulator devices.
@@ -34,7 +34,10 @@ KBSS specific properties:
		    "qcom,cprh-msm8998-v1-kbss-regulator",
		    "qcom,cprh-msm8998-v2-kbss-regulator",
		    "qcom,cprh-msm8998-kbss-regulator",
		    "qcom,cprh-sdm660-kbss-regulator".
		    "qcom,cprh-sdm660-kbss-regulator",
		    "qcom,cprh-sdm845-v1-kbss-regulator",
		    "qcom,cprh-sdm845-v2-kbss-regulator",
		    "qcom,cprh-sdm845-kbss-regulator".
		    If the SoC revision is not specified, then it is assumed to
		    be the most recent revision of MSM8998, i.e. v2.

@@ -242,7 +245,7 @@ KBSS specific properties:
		    qcom,cpr-speed-bins number of elements.

- qcom,corner-band-allow-core-count-adjustment
	Usage:      optional
	Usage:      optional; only allowed for CPRh thread 0
	Value type: <prop-encoded-array>
	Definition: A list of integer tuples which each define the CPR core
		    count adjustment feature enable state for each corner band
@@ -271,7 +274,7 @@ KBSS specific properties:
		    adjustments specified for this regulator's corner bands.

- qcom,corner-band-allow-temp-adjustment
	Usage:      optional
	Usage:      optional; only allowed for CPRh thread 0
	Value type: <prop-encoded-array>
	Definition: A list of integer tuples which each define the temperature
		    adjustment feature enable state for each corner band
+100 −21
Original line number Diff line number Diff line
@@ -45,6 +45,9 @@
#define CPR3_RO_MASK			GENMASK(CPR3_RO_COUNT - 1, 0)

/* CPR3 registers */
#define CPR3_REG_CPR_VERSION			0x0
#define CPRH_CPR_VERSION_4P5			0x40050000

#define CPR3_REG_CPR_CTL			0x4
#define CPR3_CPR_CTL_LOOP_EN_MASK		BIT(0)
#define CPR3_CPR_CTL_LOOP_ENABLE		BIT(0)
@@ -228,7 +231,10 @@
#define CPR4_CPR_MASK_THREAD_RO_MASK4THREAD_MASK	GENMASK(15, 0)

/* CPRh controller specific registers and bit definitions */
#define CPRH_REG_CORNER(corner)	(0x3A00 + 0x4 * (corner))
#define CPRH_REG_CORNER(thread, corner) \
		((thread)->ctrl->cpr_hw_version >= CPRH_CPR_VERSION_4P5 \
			? 0x3500 + 0xA0 * (thread)->thread_id + 0x4 * (corner) \
			: 0x3A00 + 0x4 * (corner))
#define CPRH_CORNER_INIT_VOLTAGE_MASK		GENMASK(7, 0)
#define CPRH_CORNER_INIT_VOLTAGE_SHIFT		0
#define CPRH_CORNER_FLOOR_VOLTAGE_MASK		GENMASK(15, 8)
@@ -244,7 +250,8 @@
#define CPRH_CORNER_FLOOR_VOLTAGE_MAX_VALUE	255
#define CPRH_CORNER_QUOT_DELTA_MAX_VALUE	511

#define CPRH_REG_CTL				0x3AA0
#define CPRH_REG_CTL(ctrl) \
	     ((ctrl)->cpr_hw_version >= CPRH_CPR_VERSION_4P5 ? 0x3A80 : 0x3AA0)
#define CPRH_CTL_OSM_ENABLED			BIT(0)
#define CPRH_CTL_BASE_VOLTAGE_MASK		GENMASK(10, 1)
#define CPRH_CTL_BASE_VOLTAGE_SHIFT		1
@@ -257,7 +264,9 @@
#define CPRH_CTL_LAST_KNOWN_VOLTAGE_MARGIN_MASK		GENMASK(31, 29)
#define CPRH_CTL_LAST_KNOWN_VOLTAGE_MARGIN_SHIFT	29

#define CPRH_REG_STATUS			0x3AA4
#define CPRH_REG_STATUS(thread) \
		((thread)->ctrl->cpr_hw_version >= CPRH_CPR_VERSION_4P5 \
			? 0x3A84 + 0x4 * (thread)->thread_id : 0x3AA4)
#define CPRH_STATUS_CORNER			GENMASK(5, 0)
#define CPRH_STATUS_CORNER_LAST_VOLT_MASK	GENMASK(17, 6)
#define CPRH_STATUS_CORNER_LAST_VOLT_SHIFT	6
@@ -271,6 +280,10 @@
	((vband) == 0 ? CPR4_REG_MARGIN_TEMP_CORE(core) \
			: 0x3AB0 + 0x40 * ((vband) - 1) + 0x4 * (core))

/* SAW module registers */
#define SAW_REG_AVS_CTL				0x904
#define SAW_REG_AVS_LIMIT			0x908

/*
 * The amount of time to wait for the CPR controller to become idle when
 * performing an aging measurement.
@@ -1173,7 +1186,7 @@ static int cpr3_regulator_init_cprh_corners(struct cpr3_regulator *vreg)
			   i, open_loop_volt_steps, floor_volt_steps,
			   delta_quot_steps, ctrl->base_volt,
			   ctrl->step_volt, base_quots[ro_sel]);
		cpr3_write(ctrl, CPRH_REG_CORNER(i), reg);
		cpr3_write(ctrl, CPRH_REG_CORNER(vreg->thread, i), reg);
	}

free_base_quots:
@@ -1197,6 +1210,7 @@ static int cpr3_regulator_init_cprh_corners(struct cpr3_regulator *vreg)
static void cprh_controller_program_sdelta(
		struct cpr3_controller *ctrl)
{
	/* Only thread 0 supports sdelta */
	struct cpr3_regulator *vreg = &ctrl->thread[0].vreg[0];
	struct cprh_corner_band *corner_band;
	struct cpr4_sdelta *sdelta;
@@ -1206,6 +1220,11 @@ static void cprh_controller_program_sdelta(
	if (!vreg->allow_core_count_adj && !vreg->allow_temp_adj)
		return;

	if (vreg->thread->thread_id != 0) {
		cpr3_err(vreg, "core count and temperature based adjustments are only allowed for CPR thread 0\n");
		return;
	}

	cpr4_regulator_init_temp_points(ctrl);

	for (i = 0; i < CPRH_CORNER_BAND_MAX_COUNT; i++) {
@@ -1287,17 +1306,21 @@ static int cpr3_regulator_init_cprh(struct cpr3_controller *ctrl)
{
	u32 reg, pmic_step_size = 1;
	u64 temp;
	int rc;
	int i, rc;

	/* Single thread, single regulator supported */
	if (ctrl->thread_count != 1) {
		cpr3_err(ctrl, "expected 1 thread but found %d\n",
	/* One or two threads each with a single regulator supported */
	if (ctrl->thread_count < 1 || ctrl->thread_count > 2) {
		cpr3_err(ctrl, "expected 1 or 2 threads but found %d\n",
			ctrl->thread_count);
		return -EINVAL;
	} else if (ctrl->thread[0].vreg_count != 1) {
		cpr3_err(ctrl, "expected 1 regulator but found %d\n",
		cpr3_err(ctrl, "expected 1 regulator for thread 0 but found %d\n",
			ctrl->thread[0].vreg_count);
		return -EINVAL;
	} else if (ctrl->thread_count == 2 && ctrl->thread[1].vreg_count != 1) {
		cpr3_err(ctrl, "expected 1 regulator for thread 1 but found %d\n",
			ctrl->thread[1].vreg_count);
		return -EINVAL;
	}

	rc = cprh_regulator_aging_adjust(ctrl);
@@ -1312,11 +1335,13 @@ static int cpr3_regulator_init_cprh(struct cpr3_controller *ctrl)

	cprh_controller_program_sdelta(ctrl);

	rc = cpr3_regulator_init_cprh_corners(&ctrl->thread[0].vreg[0]);
	for (i = 0; i < ctrl->thread_count; i++) {
		rc = cpr3_regulator_init_cprh_corners(&ctrl->thread[i].vreg[0]);
		if (rc) {
			cpr3_err(ctrl, "failed to initialize CPRh corner registers\n");
			return rc;
		}
	}

	if (ctrl->saw_use_unit_mV)
		pmic_step_size = ctrl->step_volt / 1000;
@@ -1368,7 +1393,7 @@ static int cpr3_regulator_init_cprh(struct cpr3_controller *ctrl)
			* (u64)ctrl->corner_switch_delay_time;
		do_div(temp, 1000000000);
		do_div(temp, CPRH_MODE_SWITCH_DELAY_FACTOR);
		cpr3_masked_write(ctrl, CPRH_REG_CTL,
		cpr3_masked_write(ctrl, CPRH_REG_CTL(ctrl),
				  CPRH_CTL_MODE_SWITCH_DELAY_MASK,
				  temp << CPRH_CTL_MODE_SWITCH_DELAY_SHIFT);
	}
@@ -1386,7 +1411,7 @@ static int cpr3_regulator_init_cprh(struct cpr3_controller *ctrl)
		& CPRH_CTL_VOLTAGE_MULTIPLIER_MASK;
	/* Enable OSM block interface with CPR */
	reg |= CPRH_CTL_OSM_ENABLED;
	cpr3_masked_write(ctrl, CPRH_REG_CTL, CPRH_CTL_BASE_VOLTAGE_MASK
	cpr3_masked_write(ctrl, CPRH_REG_CTL(ctrl), CPRH_CTL_BASE_VOLTAGE_MASK
			  | CPRH_CTL_VOLTAGE_MULTIPLIER_MASK
			  | CPRH_CTL_OSM_ENABLED, reg);

@@ -1427,6 +1452,8 @@ static int cpr3_regulator_init_ctrl(struct cpr3_controller *ctrl)
	}
	ctrl->cpr_enabled = true;

	ctrl->cpr_hw_version = cpr3_read(ctrl, CPR3_REG_CPR_VERSION);

	/* Find all RO's used by any corner of any regulator. */
	for (i = 0; i < ctrl->thread_count; i++)
		for (j = 0; j < ctrl->thread[i].vreg_count; j++)
@@ -1589,6 +1616,60 @@ static int cpr3_regulator_init_ctrl(struct cpr3_controller *ctrl)
	return 0;
}

/**
 * cpr3_regulator_init_hw_closed_loop_dependencies() - perform hardware
 *		initialization steps to ensure that CPR HW closed-loop voltage
 *		change requests are able to reach the PMIC regulator
 * @pdev:		Platform device pointer for the CPR3 controller
 * @ctrl:		Pointer to the CPR3 controller
 *
 * Return: 0 on success, errno on failure
 */
static int
cpr3_regulator_init_hw_closed_loop_dependencies(struct platform_device *pdev,
		struct cpr3_controller *ctrl)
{
	struct resource *res;
	int rc = 0;
	u32 val;

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "saw");
	if (res && res->start)
		ctrl->saw_base = devm_ioremap(&pdev->dev, res->start,
					resource_size(res));

	if (ctrl->saw_base) {
		/* Configure SAW registers directly. */
		rc = of_property_read_u32(ctrl->dev->of_node,
					"qcom,saw-avs-ctrl", &val);
		if (rc) {
			cpr3_err(ctrl, "unable to read DT property qcom,saw-avs-ctrl, rc=%d\n",
				rc);
			return rc;
		}
		writel_relaxed(val, ctrl->saw_base + SAW_REG_AVS_CTL);

		rc = of_property_read_u32(ctrl->dev->of_node,
					"qcom,saw-avs-limit", &val);
		if (rc) {
			cpr3_err(ctrl, "unable to read DT property qcom,saw-avs-limit, rc=%d\n",
				rc);
			return rc;
		}
		writel_relaxed(val, ctrl->saw_base + SAW_REG_AVS_LIMIT);
	} else {
		/* Wait for SPM driver to configure SAW registers. */
		rc = msm_spm_probe_done();
		if (rc) {
			if (rc != -EPROBE_DEFER)
				cpr3_err(ctrl, "spm unavailable, rc=%d\n", rc);
			return rc;
		}
	}

	return 0;
}

/**
 * cpr3_regulator_set_target_quot() - configure the target quotient for each
 *		RO of the CPR3 thread and set the RO mask
@@ -4506,7 +4587,7 @@ static int cprh_regulator_get_voltage(struct regulator_dev *rdev)
		ctrl->cpr_enabled = true;
	}

	reg = cpr3_read(vreg->thread->ctrl, CPRH_REG_STATUS);
	reg = cpr3_read(vreg->thread->ctrl, CPRH_REG_STATUS(vreg->thread));

	if (!cpr_enabled) {
		cpr3_clock_disable(ctrl);
@@ -6332,12 +6413,10 @@ int cpr3_regulator_register(struct platform_device *pdev,
	}

	if (ctrl->supports_hw_closed_loop) {
		rc = msm_spm_probe_done();
		if (rc) {
			if (rc != -EPROBE_DEFER)
				cpr3_err(ctrl, "spm unavailable, rc=%d\n", rc);
		rc = cpr3_regulator_init_hw_closed_loop_dependencies(pdev,
								     ctrl);
		if (rc)
			return rc;
		}

		if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
			ctrl->ceiling_irq = platform_get_irq_byname(pdev,
+6 −0
Original line number Diff line number Diff line
@@ -550,6 +550,9 @@ struct cpr3_panic_regs_info {
 *			that this CPR3 controller manages.
 * @cpr_ctrl_base:	Virtual address of the CPR3 controller base register
 * @fuse_base:		Virtual address of fuse row 0
 * @saw_base:		Virtual address of the SAW module base register.  This
 *			is used for CPR controllers that support HW closed-loop
 *			on platforms which lack an SPM.
 * @aging_possible_reg:	Virtual address of an optional platform-specific
 *			register that must be ready to determine if it is
 *			possible to perform an aging measurement.
@@ -565,6 +568,7 @@ struct cpr3_panic_regs_info {
 * @soc_revision:	Revision number of the SoC.  This may be unused by
 *			platforms that do not have different behavior for
 *			different SoC revisions.
 * @cpr_hw_version:	CPR controller version register value
 * @lock:		Mutex lock used to ensure mutual exclusion between
 *			all of the threads associated with the controller
 * @vdd_regulator:	Pointer to the VDD supply regulator which this CPR3
@@ -757,6 +761,7 @@ struct cpr3_controller {
	int			ctrl_id;
	void __iomem		*cpr_ctrl_base;
	void __iomem		*fuse_base;
	void __iomem		*saw_base;
	void __iomem		*aging_possible_reg;
	struct list_head	list;
	struct cpr3_thread	*thread;
@@ -764,6 +769,7 @@ struct cpr3_controller {
	u8			*sensor_owner;
	int			sensor_count;
	int			soc_revision;
	u32			cpr_hw_version;
	struct mutex		lock;
	struct regulator	*vdd_regulator;
	struct regulator	*system_regulator;
+469 −69

File changed.

Preview size limit exceeded, changes collapsed.