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

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

Merge "regulator: qpnp-labibb: add support to configure PFM for LAB regulator"

parents 25d7561a 08cbd79f
Loading
Loading
Loading
Loading
+15 −3
Original line number Diff line number Diff line
@@ -93,7 +93,18 @@ LAB subnode required properties:
						1130, 1070, 1010, 960, 910.
- qcom,qpnp-lab-limit-maximum-current:		The maximum inductor current limit in
						mA of LAB regulator. Supported values
						are 200, 400, 600 and 800.
						are 200, 400, 600, 800, 1000, 1200,
						1400 and 1600.
- interrupts:				Specify the interrupts as per the interrupt
					encoding.
					Currently "lab-vreg-ok" is required for
					LCD mode in pmicobalt. For AMOLED mode,
					"lab-vreg-ok" is required only when SWIRE
					control is enabled and skipping 2nd SWIRE
					pulse is required in pmi8952/8996.
- interrupt-names:			Interrupt names to match up 1-to-1 with
					the interrupts specified in 'interrupts'
					property.

LAB subnode optional properties:

@@ -229,7 +240,8 @@ Example:
				reg = <0xde00 0x100>;
				reg-names = "lab";

				interrupts = <0x3 0xde 0x0>;
				interrupts = <0x3 0xde 0x0
						IRQ_TYPE_EDGE_RISING>;
                                interrupt-names = "lab-vreg-ok";

				regulator-name = "lab_reg";
@@ -249,7 +261,7 @@ Example:
				qcom,qpnp-lab-full-pull-down;
				qcom,qpnp-lab-pull-down-enable;
				qcom,qpnp-lab-switching-clock-frequency = <1600>;
				qcom,qpnp-lab-limit-maximum-current = <800>;
				qcom,qpnp-lab-limit-maximum-current = <1600>;
				qcom,qpnp-lab-limit-max-current-enable;
				qcom,qpnp-lab-ps-threshold = <40>;
				qcom,qpnp-lab-ps-enable;
+1 −1
Original line number Diff line number Diff line
@@ -497,7 +497,7 @@
				qcom,qpnp-lab-pull-down-enable;
				qcom,qpnp-lab-switching-clock-frequency =
									<1600>;
				qcom,qpnp-lab-limit-maximum-current = <800>;
				qcom,qpnp-lab-limit-maximum-current = <1600>;
				qcom,qpnp-lab-limit-max-current-enable;
				qcom,qpnp-lab-ps-threshold = <20>;
				qcom,qpnp-lab-ps-enable;
+4 −1
Original line number Diff line number Diff line
@@ -555,6 +555,9 @@
				regulator-min-microvolt = <4600000>;
				regulator-max-microvolt = <6000000>;

				interrupts = <0x3 0xde 0x0
						IRQ_TYPE_EDGE_RISING>;
				interrupt-names = "lab-vreg-ok";
				qcom,qpnp-lab-min-voltage = <4600000>;
				qcom,qpnp-lab-step-size = <100000>;
				qcom,qpnp-lab-slew-rate = <5000>;
@@ -569,7 +572,7 @@
				qcom,qpnp-lab-pull-down-enable;
				qcom,qpnp-lab-switching-clock-frequency =
									<1600>;
				qcom,qpnp-lab-limit-maximum-current = <800>;
				qcom,qpnp-lab-limit-maximum-current = <1600>;
				qcom,qpnp-lab-limit-max-current-enable;
				qcom,qpnp-lab-ps-threshold = <20>;
				qcom,qpnp-lab-ps-enable;
+163 −24
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@

#define QPNP_LABIBB_REGULATOR_DRIVER_NAME	"qcom,qpnp-labibb-regulator"

#define REG_REVISION_2			0x01
#define REG_PERPH_TYPE			0x04

#define QPNP_LAB_TYPE			0x24
@@ -60,6 +61,7 @@
#define REG_LAB_PRECHARGE_CTL		0x5E
#define REG_LAB_SOFT_START_CTL		0x5F
#define REG_LAB_SPARE_CTL		0x60
#define REG_LAB_PFM_CTL			0x62

/* LAB register bits definitions */

@@ -91,9 +93,9 @@
#define LAB_IBB_EN_RDY_EN		BIT(7)

/* REG_LAB_CURRENT_LIMIT */
#define LAB_CURRENT_LIMIT_BITS		3
#define LAB_CURRENT_LIMIT_MASK		((1 << LAB_CURRENT_LIMIT_BITS) - 1)
#define LAB_CURRENT_LIMIT_EN		BIT(7)
#define LAB_CURRENT_LIMIT_MASK		GENMASK(2, 0)
#define LAB_CURRENT_LIMIT_EN_BIT	BIT(7)
#define LAB_OVERRIDE_CURRENT_MAX_BIT	BIT(3)

/* REG_LAB_CURRENT_SENSE */
#define LAB_CURRENT_SENSE_GAIN_BITS	2
@@ -129,6 +131,9 @@
#define LAB_SPARE_TOUCH_WAKE_BIT	BIT(3)
#define LAB_SPARE_DISABLE_SCP_BIT	BIT(0)

/* REG_LAB_PFM_CTL */
#define LAB_PFM_EN_BIT			BIT(7)

/* IBB register offset definitions */
#define REG_IBB_REVISION4		0x03
#define REG_IBB_STATUS1			0x08
@@ -344,6 +349,10 @@ static const int lab_current_limit_plan[] = {
	400,
	600,
	800,
	1000,
	1200,
	1400,
	1600,
};

static const char * const lab_current_sense_plan[] = {
@@ -471,6 +480,8 @@ struct qpnp_labibb {
	struct pmic_revid_data		*pmic_rev_id;
	u16				lab_base;
	u16				ibb_base;
	u8				lab_dig_major;
	u8				ibb_dig_major;
	struct lab_regulator		lab_vreg;
	struct ibb_regulator		ibb_vreg;
	enum qpnp_labibb_mode		mode;
@@ -481,6 +492,7 @@ struct qpnp_labibb {
	bool				swire_control;
	bool				ttw_force_lab_on;
	bool				skip_2nd_swire_cmd;
	bool				pfm_enable;
	u32				swire_2nd_cmd_delay;
	u32				swire_ibb_ps_enable_delay;
};
@@ -783,7 +795,7 @@ static int qpnp_lab_dt_init(struct qpnp_labibb *labibb,

	if (of_property_read_bool(of_node,
		"qcom,qpnp-lab-limit-max-current-enable"))
		val |= LAB_CURRENT_LIMIT_EN;
		val |= LAB_CURRENT_LIMIT_EN_BIT;

	rc = qpnp_labibb_write(labibb, labibb->lab_base +
				REG_LAB_CURRENT_LIMIT, &val, 1);
@@ -936,6 +948,88 @@ static int qpnp_lab_dt_init(struct qpnp_labibb *labibb,
	return rc;
}

#define LAB_CURRENT_MAX_1600MA	0x7
#define LAB_CURRENT_MAX_400MA	0x1
static int qpnp_lab_pfm_disable(struct qpnp_labibb *labibb)
{
	int rc = 0;
	u8 val, mask;

	mutex_lock(&(labibb->lab_vreg.lab_mutex));
	if (!labibb->pfm_enable) {
		pr_debug("PFM already disabled\n");
		goto out;
	}

	val = 0;
	mask = LAB_PFM_EN_BIT;
	rc = qpnp_labibb_masked_write(labibb, labibb->lab_base +
				REG_LAB_PFM_CTL, mask, val);
	if (rc < 0) {
		pr_err("Write register %x failed rc = %d\n",
			REG_LAB_PFM_CTL, rc);
		goto out;
	}

	val = LAB_CURRENT_MAX_1600MA;
	mask = LAB_OVERRIDE_CURRENT_MAX_BIT | LAB_CURRENT_LIMIT_MASK;
	rc = qpnp_labibb_masked_write(labibb, labibb->lab_base +
				REG_LAB_CURRENT_LIMIT, mask, val);
	if (rc < 0) {
		pr_err("Write register %x failed rc = %d\n",
			REG_LAB_CURRENT_LIMIT, rc);
		goto out;
	}

	labibb->pfm_enable = false;
out:
	mutex_unlock(&(labibb->lab_vreg.lab_mutex));
	return rc;
}

static int qpnp_lab_pfm_enable(struct qpnp_labibb *labibb)
{
	int rc = 0;
	u8 val, mask;

	mutex_lock(&(labibb->lab_vreg.lab_mutex));
	if (labibb->pfm_enable) {
		pr_debug("PFM already enabled\n");
		goto out;
	}

	/* Wait for ~100uS */
	usleep_range(100, 105);

	val = LAB_OVERRIDE_CURRENT_MAX_BIT | LAB_CURRENT_MAX_400MA;
	mask = LAB_OVERRIDE_CURRENT_MAX_BIT | LAB_CURRENT_LIMIT_MASK;
	rc = qpnp_labibb_masked_write(labibb, labibb->lab_base +
				REG_LAB_CURRENT_LIMIT, mask, val);
	if (rc < 0) {
		pr_err("Write register %x failed rc = %d\n",
			REG_LAB_CURRENT_LIMIT, rc);
		goto out;
	}

	/* Wait for ~100uS */
	usleep_range(100, 105);

	val = LAB_PFM_EN_BIT;
	mask = LAB_PFM_EN_BIT;
	rc = qpnp_labibb_masked_write(labibb, labibb->lab_base +
				REG_LAB_PFM_CTL, mask, val);
	if (rc < 0) {
		pr_err("Write register %x failed rc = %d\n",
			REG_LAB_PFM_CTL, rc);
		goto out;
	}

	labibb->pfm_enable = true;
out:
	mutex_unlock(&(labibb->lab_vreg.lab_mutex));
	return rc;
}

static int qpnp_labibb_restore_settings(struct qpnp_labibb *labibb)
{
	int rc, i;
@@ -1435,6 +1529,15 @@ static int qpnp_labibb_regulator_disable(struct qpnp_labibb *labibb)
		return -EINVAL;
	}

	if (labibb->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE &&
		labibb->mode == QPNP_LABIBB_LCD_MODE) {
		rc = qpnp_lab_pfm_disable(labibb);
		if (rc < 0) {
			pr_err("Error in disabling PFM, rc=%d\n", rc);
			return rc;
		}
	}

	labibb->lab_vreg.vreg_enabled = 0;
	labibb->ibb_vreg.vreg_enabled = 0;

@@ -1644,9 +1747,17 @@ static irqreturn_t lab_vreg_ok_handler(int irq, void *_labibb)
	struct qpnp_labibb *labibb = _labibb;
	int rc;

	if (labibb->skip_2nd_swire_cmd && labibb->lab_dig_major < 2) {
		rc = qpnp_skip_swire_command(labibb);
	if (rc)
		pr_err("Failed in 'qpnp_skip_swire_command' rc=%d\n", rc);
		if (rc < 0)
			pr_err("Failed in 'qpnp_skip_swire_command' rc=%d\n",
				rc);
	} else if (labibb->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE &&
		labibb->mode == QPNP_LABIBB_LCD_MODE) {
		rc = qpnp_lab_pfm_enable(labibb);
		if (rc < 0)
			pr_err("Failed to config PFM, rc=%d\n", rc);
	}

	return IRQ_HANDLED;
}
@@ -1661,6 +1772,23 @@ static int qpnp_lab_regulator_get_voltage(struct regulator_dev *rdev)
	return labibb->lab_vreg.curr_volt;
}

static bool is_lab_vreg_ok_irq_available(struct qpnp_labibb *labibb)
{
	/*
	 * LAB VREG_OK interrupt is used only to skip 2nd SWIRE command in
	 * dig_major < 2 targets. For pmicobalt, it is used to enable PFM in
	 * LCD mode.
	 */
	if (labibb->skip_2nd_swire_cmd && labibb->lab_dig_major < 2)
		return true;

	if (labibb->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE &&
		labibb->mode == QPNP_LABIBB_LCD_MODE)
		return true;

	return false;
}

static struct regulator_ops qpnp_lab_ops = {
	.enable			= qpnp_lab_regulator_enable,
	.disable		= qpnp_lab_regulator_disable,
@@ -1809,19 +1937,6 @@ static int register_qpnp_lab_regulator(struct qpnp_labibb *labibb,
		}
	}

	if (labibb->skip_2nd_swire_cmd) {
		rc = devm_request_threaded_irq(labibb->dev,
				labibb->lab_vreg.lab_vreg_ok_irq, NULL,
				lab_vreg_ok_handler,
				IRQF_ONESHOT | IRQF_TRIGGER_RISING,
				"lab-vreg-ok", labibb);
		if (rc) {
			pr_err("Failed to register 'lab-vreg-ok' irq rc=%d\n",
						rc);
			return rc;
		}
	}

	val = (labibb->standalone) ? 0 : LAB_IBB_EN_RDY_EN;
	rc = qpnp_labibb_sec_write(labibb, labibb->lab_base,
			REG_LAB_IBB_EN_RDY, &val, 1);
@@ -1899,6 +2014,19 @@ static int register_qpnp_lab_regulator(struct qpnp_labibb *labibb,
		labibb->lab_vreg.vreg_enabled = 1;
	}

	if (is_lab_vreg_ok_irq_available(labibb)) {
		rc = devm_request_threaded_irq(labibb->dev,
				labibb->lab_vreg.lab_vreg_ok_irq, NULL,
				lab_vreg_ok_handler,
				IRQF_ONESHOT | IRQF_TRIGGER_RISING,
				"lab-vreg-ok", labibb);
		if (rc) {
			pr_err("Failed to register 'lab-vreg-ok' irq rc=%d\n",
						rc);
			return rc;
		}
	}

	rc = qpnp_labibb_read(labibb, &val,
			labibb->lab_base + REG_LAB_MODULE_RDY, 1);
	if (rc) {
@@ -1953,7 +2081,6 @@ static int register_qpnp_lab_regulator(struct qpnp_labibb *labibb,
		return -EINVAL;
	}

	mutex_init(&(labibb->lab_vreg.lab_mutex));
	return 0;
}

@@ -2683,14 +2810,13 @@ static int register_qpnp_ibb_regulator(struct qpnp_labibb *labibb,
		return -EINVAL;
	}

	mutex_init(&(labibb->ibb_vreg.ibb_mutex));
	return 0;
}

static int qpnp_lab_register_irq(struct device_node *child,
				struct qpnp_labibb *labibb)
{
	if (labibb->skip_2nd_swire_cmd) {
	if (is_lab_vreg_ok_irq_available(labibb)) {
		labibb->lab_vreg.lab_vreg_ok_irq =
					of_irq_get_byname(child, "lab-vreg-ok");
		if (labibb->lab_vreg.lab_vreg_ok_irq < 0) {
@@ -2745,7 +2871,7 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev)
	unsigned int base;
	struct device_node *child, *revid_dev_node;
	const char *mode_name;
	u8 type;
	u8 type, revision;
	int rc = 0;

	labibb = devm_kzalloc(&pdev->dev,
@@ -2763,6 +2889,9 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev)
	labibb->dev = &(pdev->dev);
	labibb->pdev = pdev;

	mutex_init(&(labibb->lab_vreg.lab_mutex));
	mutex_init(&(labibb->ibb_vreg.ibb_mutex));

	revid_dev_node = of_parse_phandle(labibb->dev->of_node,
					"qcom,pmic-revid", 0);
	if (!revid_dev_node) {
@@ -2817,6 +2946,7 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev)
		labibb->skip_2nd_swire_cmd =
				of_property_read_bool(labibb->dev->of_node,
				"qcom,skip-2nd-swire-cmd");

		rc = of_property_read_u32(labibb->dev->of_node,
				"qcom,swire-2nd-cmd-delay",
				&labibb->swire_2nd_cmd_delay);
@@ -2846,6 +2976,13 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev)
			return rc;
		}

		rc = qpnp_labibb_read(labibb, &revision, base + REG_REVISION_2,
					1);
		if (rc) {
			pr_err("Reading REVISION_2 failed rc=%d\n", rc);
			goto fail_registration;
		}

		rc = qpnp_labibb_read(labibb, &type,
				base + REG_PERPH_TYPE, 1);
		if (rc) {
@@ -2856,6 +2993,7 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev)
		switch (type) {
		case QPNP_LAB_TYPE:
			labibb->lab_base = base;
			labibb->lab_dig_major = revision;
			rc = qpnp_lab_register_irq(child, labibb);
			if (rc) {
				pr_err("Failed to register LAB IRQ rc=%d\n",
@@ -2869,6 +3007,7 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev)

		case QPNP_IBB_TYPE:
			labibb->ibb_base = base;
			labibb->ibb_dig_major = revision;
			rc = register_qpnp_ibb_regulator(labibb, child);
			if (rc)
				goto fail_registration;