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

Commit 968862c9 authored by Anirudh Ghayal's avatar Anirudh Ghayal Committed by Gerrit - the friendly Code Review server
Browse files

regulator: qpnp-lcdb: Add a WA to toggle SC before module_enable



There is a possibility of the NCP failing to turn on due
to an invalid (short circuit) SC event before the LCDB module
is enabled.

Force a SC re-enable to recover from this condition. Enable this
for PM660L V1.1.

Also, disable the SC handling logic for PM660L to avoid
permanently disabling the module due to the above mentioned
issue.

CRs-Fixed: 2025449
Change-Id: I191d11c35c3d96727874818b8b57fa1c254879bf
Signed-off-by: default avatarAnirudh Ghayal <aghayal@codeaurora.org>
parent 14416b24
Loading
Loading
Loading
Loading
+4 −6
Original line number Diff line number Diff line
@@ -26,12 +26,10 @@ First Level Node - LCDB module
	Value type: <prop-encoded-array>
	Definition:  Base address of the LCDB SPMI peripheral.

- qcom,force-module-reenable
	Usage:      required if using SW mode for module enable
	Value type:  <bool>
	Definition: This enables the workaround to force enable
		    the vph_pwr_2p5_ok signal required for
		    turning on the LCDB module.
- qcom,pmic-revid
	Usage:      required
	Value type: <phandle>
	Definition:  Phandle to the PMIC's revid node

Touch-to-wake (TTW) properties:

+89 −26
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include <linux/regulator/driver.h>
#include <linux/regulator/of_regulator.h>
#include <linux/regulator/machine.h>
#include <linux/qpnp/qpnp-revid.h>

#define QPNP_LCDB_REGULATOR_DRIVER_NAME		"qcom,qpnp-lcdb-regulator"

@@ -192,6 +193,7 @@ struct qpnp_lcdb {
	struct device			*dev;
	struct platform_device		*pdev;
	struct regmap			*regmap;
	struct pmic_revid_data		*pmic_rev_id;
	u32				base;
	int				sc_irq;

@@ -199,9 +201,6 @@ struct qpnp_lcdb {
	bool				ttw_enable;
	bool				ttw_mode_sw;

	/* top level DT params */
	bool				force_module_reenable;

	/* status parameters */
	bool				lcdb_enabled;
	bool				settings_saved;
@@ -579,6 +578,65 @@ static int qpnp_lcdb_ttw_exit(struct qpnp_lcdb *lcdb)
	return 0;
}

static int qpnp_lcdb_enable_wa(struct qpnp_lcdb *lcdb)
{
	int rc;
	u8 val = 0;

	/* required only for PM660L */
	if (lcdb->pmic_rev_id->pmic_subtype != PM660L_SUBTYPE)
		return 0;

	val = MODULE_EN_BIT;
	rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_ENABLE_CTL1_REG,
						&val, 1);
	if (rc < 0) {
		pr_err("Failed to enable lcdb rc= %d\n", rc);
		return rc;
	}

	val = 0;
	rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_ENABLE_CTL1_REG,
							&val, 1);
	if (rc < 0) {
		pr_err("Failed to disable lcdb rc= %d\n", rc);
		return rc;
	}

	/* execute the below for rev1.1 */
	if (lcdb->pmic_rev_id->rev3 == PM660L_V1P1_REV3 &&
		lcdb->pmic_rev_id->rev4 == PM660L_V1P1_REV4) {
		/*
		 * delay to make sure that the MID pin – ie the
		 * output of the LCDB boost – returns to 0V
		 * after the module is disabled
		 */
		usleep_range(10000, 10100);

		rc = qpnp_lcdb_masked_write(lcdb,
				lcdb->base + LCDB_MISC_CTL_REG,
				DIS_SCP_BIT, DIS_SCP_BIT);
		if (rc < 0) {
			pr_err("Failed to disable SC rc=%d\n", rc);
			return rc;
		}
		/* delay for SC-disable to take effect */
		usleep_range(1000, 1100);

		rc = qpnp_lcdb_masked_write(lcdb,
				lcdb->base + LCDB_MISC_CTL_REG,
				DIS_SCP_BIT, 0);
		if (rc < 0) {
			pr_err("Failed to enable SC rc=%d\n", rc);
			return rc;
		}
		/* delay for SC-enable to take effect */
		usleep_range(1000, 1100);
	}

	return 0;
}

static int qpnp_lcdb_enable(struct qpnp_lcdb *lcdb)
{
	int rc = 0, timeout, delay;
@@ -598,22 +656,12 @@ static int qpnp_lcdb_enable(struct qpnp_lcdb *lcdb)
		}
	}

	val = MODULE_EN_BIT;
	rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_ENABLE_CTL1_REG,
							&val, 1);
	rc = qpnp_lcdb_enable_wa(lcdb);
	if (rc < 0) {
		pr_err("Failed to enable lcdb rc= %d\n", rc);
		goto fail_enable;
		pr_err("Failed to execute enable_wa rc=%d\n", rc);
		return rc;
	}

	if (lcdb->force_module_reenable) {
		val = 0;
		rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_ENABLE_CTL1_REG,
								&val, 1);
		if (rc < 0) {
			pr_err("Failed to enable lcdb rc= %d\n", rc);
			goto fail_enable;
		}
	val = MODULE_EN_BIT;
	rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_ENABLE_CTL1_REG,
							&val, 1);
@@ -621,7 +669,6 @@ static int qpnp_lcdb_enable(struct qpnp_lcdb *lcdb)
		pr_err("Failed to disable lcdb rc= %d\n", rc);
		goto fail_enable;
	}
	}

	/* poll for vreg_ok */
	timeout = 10;
@@ -1674,7 +1721,8 @@ static int qpnp_lcdb_hw_init(struct qpnp_lcdb *lcdb)
		return rc;
	}

	if (lcdb->sc_irq >= 0) {
	if (lcdb->sc_irq >= 0 &&
		lcdb->pmic_rev_id->pmic_subtype != PM660L_SUBTYPE) {
		lcdb->sc_count = 0;
		rc = devm_request_threaded_irq(lcdb->dev, lcdb->sc_irq,
				NULL, qpnp_lcdb_sc_irq_handler, IRQF_ONESHOT,
@@ -1714,8 +1762,26 @@ static int qpnp_lcdb_parse_dt(struct qpnp_lcdb *lcdb)
{
	int rc = 0;
	const char *label;
	struct device_node *temp, *node = lcdb->dev->of_node;
	struct device_node *revid_dev_node, *temp, *node = lcdb->dev->of_node;

	revid_dev_node = of_parse_phandle(node, "qcom,pmic-revid", 0);
	if (!revid_dev_node) {
		pr_err("Missing qcom,pmic-revid property - fail driver\n");
		return -EINVAL;
	}

	lcdb->pmic_rev_id = get_revid_data(revid_dev_node);
	if (IS_ERR(lcdb->pmic_rev_id)) {
		pr_debug("Unable to get revid data\n");
		/*
		 * revid should to be defined, return -EPROBE_DEFER
		 * until the revid module registers.
		 */
		of_node_put(revid_dev_node);
		return -EPROBE_DEFER;
	}

	of_node_put(revid_dev_node);
	for_each_available_child_of_node(node, temp) {
		rc = of_property_read_string(temp, "label", &label);
		if (rc < 0) {
@@ -1742,9 +1808,6 @@ static int qpnp_lcdb_parse_dt(struct qpnp_lcdb *lcdb)
		}
	}

	lcdb->force_module_reenable = of_property_read_bool(node,
					"qcom,force-module-reenable");

	if (of_property_read_bool(node, "qcom,ttw-enable")) {
		rc = qpnp_lcdb_parse_ttw(lcdb);
		if (rc < 0) {